Если это действительно так просто, вы можете написать это с помощью printf () или подобного.
Для синтаксического анализа лучше всего использовать настоящий анализатор XML (возможно, SimpleXML, предложенный @netpork). Но для чего-то действительно этого тривиального, вы можете просто использовать регулярные выражения - вот мой обычный набор, из которого вам понадобятся в основном «attrlist» и «stag» (для списка атрибутов и начального тега).
xname = "([_\\w][-_:.\\w\\d]*)"; # XML NAME (imperfect charset)
xnmtoken = "([-_:.\\w\\d]+)"; #
xncname = "([_\\w][-_.\\w\\d]*)"; #
qlit = '("[^"]*"|\'[^\']*\')'; # Includes the quotes
attr = "$xname\\s*=\\s*$qlit"; # Captures name and value
attrlist = "(\\s+$attr)*"; #
startTag = "<$xname$attrlist\\s*/?>"; #
endTag = "</$xname\\s*>"; #
comment = "(<!--[^-]*(-[^-]+)*-->)"; # Includes delims
pi = "(<\?$xname.*?\?>)"; # Processing instruction
dcl = "(<!$xname\\s+[^>]+>)"; # Markup dcl (imperfect)
cdataStart = "(<!\[CDATA\[)"; # Marked section open
cdataEnd = "(]]>)"; # Marked section close
charRef = "&(#\\d+|#[xX][0-9a-fA-F]+);"; # Num char ref (no delims)
entRef = "&$xname;"; # Named entity ref
pentRef = "%$xname;"; # Parameter entity ref
xtext = "[^<&]*"; # Neglects ']]>'
xdocument = "^($startTag|$endTag|$pi|$comment|$entRef|$xtext)+\$";
Черновик спецификации XML даже включал «тривиальную» грамматику для XML, которая может правильно находить границы узлов, но не перехватывать все ошибки, расширять ссылки на сущности и т. Д. См. https://www.w3.org/TR/WD-xml-lang-970630#secF.
Основным недостатком является то, что если вы столкнетесь с более интересными данными позже, они могут сломаться. Например, кто-то может отправить вам данные с комментарием, или синтаксической ошибкой, или атрибутом без кавычек, или использовать & quo; или что-то еще.