1

I'm using the DOMDocument class to parse a fairly unpredictable string of markup. It's not all that well formed and I need some data from it. Regex's are right out, of course.
So far, I've got this:

$dom = new DOMDocument;
$dom->loadHTML($str);
$contents = $dom->getElementsByTagName('body')->item(0);
echo $dom->saveXML($contents);

Now this gives me:

<body>
    <p>What I'm really after</p>
    <ul><li>Foo</li><li>Bar</li></ul>
    <h6>And so on</h6>
</body>

What really annoys me are those <body> tags. I want them gone. After grazing the web, I've stumbled across the weirdest workarounds. Some more hacky than others, so in the end, I settled for:

echo substr($dom->saveXML($contents), 6, -7);

Still feels hacky to me, but it's the best I could find. Is there a more reliable way of getting the innerHTML of the DOM, starting from a given node, without the corresponding tags actually showing up?

I've seen suggestions using regex's (a no-no IMHO), or even looping through all the children, echoing those that have childNodes of their own, and stringing together those that don't:

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.'>';
    }
}

But that, to me, seems even more absurd...

5
  • is the <body> tag always present? Do you want to remove ALL the tags? Commented May 30, 2013 at 15:58
  • @Harsh: The <body> tag is being added by DOMDocument (along with a doctype and <head> tag. All I want to do is parse the HTML, so I can get at some bits of data I need, and return a normalized version of the markup Commented May 30, 2013 at 16:00
  • check this out: stackoverflow.com/questions/2087103/… Commented May 30, 2013 at 16:15
  • @Harsh: I already have, compared to substr($dom->saveXML($contents), 6, -7);, the answer there is way too inefficient. Commented May 30, 2013 at 18:09
  • if you are gunning for speed, Kolink's solution isn't bad :) Commented May 30, 2013 at 19:55

1 Answer 1

1

When exporting HTML, you must have a single root element. In most cases, the most useful one is the body. Since you're loading in an HTML fragment, you know for certain that it won't have any attributes, therefore the substr(...,6,-7) is perfectly predictable and fine.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the quick response. It still feels a bit hacky... anyway: I'm done working for the day, but I'll accept your answer once I get home.
yea, it is hacky, but does the job well. Although I'd fear using this due to its opaque purpose. :P
@Harsh: That's why all programming languages I've ever used allow for comments...
@Harsh: That, and preg_replace('/^[^>]+>(.+)<[^>]+>$/',$1',$dom->saveXML($contents));, which is, in theory, a more reliable way to strip the outer tags in 1 line, calls Cthulu

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.