I'm loading a DOMDocument as follows:
$dom->loadHtml($str_html_fragment, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
The extra arguments ensures that saveHTML just outputs the fragment, and doesn't add surrounding doctypes or html tags.
$str_html_fragment could be either something like
<ul>
<li>one</li>
<li>two</li>
</ul>
or
<span>one</span>
<span>two</span>
If there is already a single root element in the fragment (like the <ul>), I want to add a class to it, but if the fragment consists of a number of sibling nodes, I want to surround the fragment with a new <div> and add the new class to that instead, to give either:
<ul class="new-class">
<li>one</li>
<li>two</li>
</ul>
or
<div class="new-class">
<span>one</span>
<span>two</span>
</div>
From looking at the docs I can't see how to count whether there are multiple elements are at the 'top level' or not, or how to add a surrounding root element after loadHTML has been called. Any help appreciated.
There is a description of the problem and a solution at php.net:
When saving HTML fragment initiated with LIBXML_HTML_NOIMPLIED option, it will end up being "broken" as libxml requires root element. libxml will attempt to fix the fragment by adding closing tag at the end of string based on the first opened tag it encounters in the fragment.
For an example:
<h1>Foo</h1><p>bar</p>will end up as:
<h1>Foo<p>bar</p></h1>Easiest workaround is adding root tag yourself and stripping it later:
$html->loadHTML('' . $content .'', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$content = str_replace(array('','') , '' , $html->saveHTML());
When I apply this to your case, I end up with the following code, which can serve as proof of concept:
<?php
$dom = new DOMDocument;
$str_html_fragment = <<<'EOD'
<span>one</span>
<span>two</span>
EOD;
$dom->loadHTML('<html>' . $str_html_fragment .'</html>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$i = 0;
foreach($dom->childNodes as $top) {
foreach($top->childNodes as $node) {
echo "Node type is " . $node->nodeType . "\n";
if($node->nodeType == XML_ELEMENT_NODE) $i += 1;
}
}
echo "We have $i element nodes\n";
echo str_replace(array('<html>','</html>') , '' , $dom->saveHTML());
?>
This code genrates the following output:
Node type is 1
Node type is 3
Node type is 1
We have 2 element nodes
<span>one</span>
<span>two</span>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With