Jak na moje oko to przedewszystkim musisz dojść do postaci XML-a. Jak już będziesz miał XML-a to już będzie z górki. Będziesz mógł przestawiac/wywalać/dodawać elementy jak tylko będziesz chciał.
Swego czasu napisałem klasę do naprawiania zepsutych XML-i. XML-e które otrzymywałem były urwane (czyli najczęściej tagi nie były podomykane). Rozwiązałem ten problem w taki oto sposób:
class MalformedXML {
private static function tagText
($parser, $str) { }
private static function tagStart
($parser, $tagName, $attr) { $t = '<'.$tagName;
foreach($attr as $key => $value) {
$t .= ' '.$key.'="'.$value.'"';
}
}
private static function tagEnd
($parser, $tagName) { }
public static function fix
(&$xml) { //Jeśli ostatni znacznik został urwany w połowie to go usuwamy
//Wywalamy wszystkie pojedyńcze znaczniki z początku dokumentu
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
xml_set_character_data_handler
($parser, array('MalformedXML', 'tagText')); xml_set_element_handler
($parser, array('MalformedXML', 'tagStart'), array('MalformedXML', 'tagEnd'));
xml_parse($parser, "<root>$xml</root>");
//Domykamy niedomknięte tagi
while(!empty(self::$tags)) { }
$doc = new DOMDocument('1.0', 'utf-8');
if ($doc->documentElement == null) {
throw new Exception("Nie udalo się naprawić");
}
$xml = $doc->saveXML($doc->documentElement);
return $xml;
}
}
$str = '<html>
<body>
<p>
<div><input type="text"></div>
</p>
<p>
<div></div>
</p>
</body>
</html>';
echo MalformedXML
::fix($str); //Wynik: <html><body><p><div><input type="text"/></div></p></body></html>
Klasa ta nie jest dokładnie przetestowana, prawdopodobnie będziesz musiał ją dostosować do swoich potrzeb.