4

I would like to be able to do the equivalent of

$html->find("#foo>ul")

But the PHP Simple DOM library doesn't recognize the "immediate descendant" selector > and so finds all <ul> items under #foo including those that are nested deeper in the dom.

What would you recommend as the best way to grab the immediate descendants that are of a specific type?

MrWhite
  • 43,179
  • 8
  • 60
  • 84
user1104799
  • 161
  • 3
  • 13

3 Answers3

3

You can use DomElementFilter to fetch the desired type of nodes under some Dom branch. This is described here:

PHP DOM: How to get child elements by tag name in an elegant manner?

Or do a regular loop on all childNodes and filter then by their tag name by yourself:

foreach ($parent->childNodes as $node)
    if ($node->nodeName == "tagname1")
        ...
Community
  • 1
  • 1
Oooogi
  • 383
  • 4
  • 14
  • 1
    Thanks ... this set me in the right direction, which was to do a general query for the 'children' of the node and then to check the tag name. – user1104799 Oct 18 '15 at 19:00
1

HTML snippet

<div id="foo">
    <ul>
        <li>1</li>
    </ul>       
    <ul>
        <li>2</li>
    </ul>       
    <ul>
        <li>3</li>
    </ul>       
</div>

PHP code to get FIRST <ul>

echo $html->find('#foo>ul', 0);

this will output

<ul>
    <li>1</li>
</ul>

but if you want to get just 1 from first <ul>

echo $html->find('#foo>ul', 0)->plaintext;
Mubin
  • 4,325
  • 5
  • 33
  • 55
  • Thanks Mubin - my situation is where I have nested UL's so the find(#foo>ul) just picks up all the UL's in #foo, not just the top level ones (php dom doesn't pay attention to the '>') – user1104799 Oct 18 '15 at 19:00
0

Just to share the solutions i found in related posts and to put it in a nutshell: "Find immediate descendants with PHP Simple DOM parser" works both with...

...PHP Simple DOM:

    //if there is only one div containing your searched tag
    foreach ($html->find('div.with-given-class')[0]->children() as $div_with_given_class) {
        if ($div_with_given_class->tag == 'tag-you-are-searching-for') {
        $output [] = $div_with_given_class->plaintext; //or whatever you want
        }
    }


    //if there are more divs with a given class (better solution)
    $all_divs_with_given_class = 
        $html->find('div.with-given-class');

    foreach ($all_divs_with_given_class as $single_div_with_given_class) {
        foreach ($single_div_with_given_class->children() as $children) {
            if ($children->tag == 'tag-you-are-searching-for') {
                $output [] = $children->plaintext; //or whatever you want
            }
        }
    } 

...and also PHP DOM/xpath:

    $all_divs_with_given_class =     
        $xpath->query("//div[@class='with-given-class']/tag-you-are-searching-for");

    if (!is_null($all_divs_with_given_class)) {
        foreach ($all_divs_with_given_class as $tag-you-are-searching-for) {
            $ouput [] = $tag-you-are-searching-for->nodeValue; //or whatever you want
        }
    }

Note that you have to use single slashes "/" in the xpath to find immediate descendants only.

Albager
  • 1
  • 1