Я использую класс DOMDocument
для анализа довольно непредсказуемой строки разметки. Это еще не все, что хорошо сформировано, и мне нужны некоторые данные. Разумеется, Regex – это все.
Пока у меня есть это:
$dom = new DOMDocument; $dom->loadHTML($str); $contents = $dom->getElementsByTagName('body')->item(0); echo $dom->saveXML($contents);
Теперь это дает мне:
<body> <p>What I'm really after</p> <ul><li>Foo</li><li>Bar</li></ul> <h6>And so on</h6> </body>
Меня действительно раздражают те теги <body>
. Я хочу, чтобы они ушли. После выпаса паутины я наткнулся на самые странные обходные пути. Еще немного хаки, чем другие, поэтому в конце концов я решил:
echo substr($dom->saveXML($contents), 6, -7);
Все еще чувствует себя взломанным для меня, но это лучшее, что я мог найти. Есть ли более надежный способ получения innerHTML DOM, начиная с данного узла, без фактических показов соответствующих тегов?
Я видел предложения с использованием регулярных выражений (no-no IMHO) или даже прокручивал все дочерние элементы, повторяя те, у которых есть собственные дочерние узлы, и строит вместе те, которые этого не делают:
if ($contents->hasChildNodes()) { $children = $contents->getElementsByTagName('*'); foreach($children as $child) { if ($child->hasChildNodes() || $child->nodeName === 'br') {//or isset($standaloneNodes[$child->nodeName]) echo $dom->saveXML($child); continue; } echo '<'.$child->nodeName.'>'.$child->nodeValue.'</'.$child->nodeName.'>'; } }
Но это для меня кажется еще более абсурдным …
При экспорте HTML вы должны иметь один корневой элемент. В большинстве случаев наиболее полезным является body
. Поскольку вы загружаете фрагмент HTML, вы наверняка знаете, что у него не будет никаких атрибутов, поэтому substr(...,6,-7)
отлично предсказуем и точнее.