Traversing child nodes with PHP DOMXpath?

16,107

Solution 1

Yes you can run another xpath query, something like that :

foreach ($nodelist as $n)
{
    $other_nodes = $xpath->query('div[@class="somethingelse"]', $n);

    echo $other_nodes->length;
}

This will get you the inner div with the class somethingelse, the second argument of the $xpath->query method tells to query to take this node as context, see more http://fr2.php.net/manual/en/domxpath.query.php

Solution 2

If I understand your question correctly, it worked when I used the descendant:: expression. Try this:

foreach ($nodelist as $n) {
    $other_nodes = $xpath->query('descendant::div[@class="some-descendant"]', $n);

    echo $other_nodes->length;
    echo $other_nodes->item(0)->nodeValue;
}

Although sometimes it's just enough to combine queries using the // path expression for narrowing your search. The // path expression selects nodes in the document starting from the current node that match the selector.

$nodes = $xpath->query('//div[@class="some-descendant"]//div[@class="some-descendant-of-that-descendant"]');

Then loop through those for the stuff you need. Hope this helps.

Solution 3

Trexx had it but he missed the last sentence of the question:

foreach ($nodelist as $n){
    $href = $xpath->query('h3/a', $n)->item(0)->getAttribute('href');
    $a_text = $xpath->query('h3/a', $n)->item(0)->nodeValue;
    $div_text = $xpath->query('div', $n)->item(0)->nodeValue;
}
Share:
16,107
Bryan
Author by

Bryan

Updated on June 05, 2022

Comments

  • Bryan
    Bryan almost 2 years

    I'm having some trouble understanding what exactly is stored in childNodes. Ideally I'd like to do another xquery on each of the child nodes, but can't seem to get it straight. Here's my scenario: Data:

    <div class="something">
        <h3>
            <a href="link1.html">Link text 1</a>
        </h3>
        <div class"somethingelse">Something else text 1</div>
    </div>
    <div class="something">
        <h3>
            <a href="link2.html">Link text 2</a>
        </h3>
        <div class"somethingelse">Something else text 2</div>
    </div>
    <div class="something">
        <h3>
            <a href="link3.html">Link text 3</a>
        </h3>
        <div class"somethingelse">Something else text 3</div>
    </div>
    

    And the code:

    $html = new DOMDocument();
    $html->loadHtmlFile($local_file);
    $xpath = new DOMXPath( $html );
    $nodelist = $xpath->query( "//div[@class='something']");
    foreach ($nodelist as $n) {
        Can I run another query here? }
    

    For each element of "something" (i.e., $n) I want to access the values of the two pieces of text and the href. I tried using childNode and another xquery but couldn't get anything to work. Any help would be greatly appreciated!

  • Bryan
    Bryan over 12 years
    Thanks @TrexXx, but when I use "$other_nodes->nodeValue" I don't see anything. Is that not starting back at the root element? I originally thought it would be something like this: $other_nodes = $n->query('div[@class="somethingelse"]');
  • mravey
    mravey over 12 years
    $other_nodes is a node list, so first you will have to get an item (a node) and then get its value. Something like $other_nodes->item(0)->nodeValue.
  • Bryan
    Bryan over 12 years
    $other_nodes ends up containing information from outside of $n (i.e. from other "something" elements); it shouldn't be the way, right? Do you know of any other approach that doesn't require going back to query the root element?
  • mravey
    mravey over 12 years
    I don't really understand what you are trying to do ?
  • Bryan
    Bryan over 12 years
    I'm trying to access (or do searches on) only the information contained within each of the original nodes (that is, the "something" elements that are looped through with $nodelist). I want to do this incase some of the elements have different or incomplete sub-information. Thanks for working through this with me.
  • Will Schoenberger
    Will Schoenberger over 9 years
    This answer got me to the solution I was looking for after I also referenced this: http://stackoverflow.com/questions/11471922/php-xpath-how-to‌​-get-two-information‌​-in-a-child-node. Check out my answer for an example.
  • sarvesh
    sarvesh over 8 years
    Thanks, I have been looping to get parent >> child result, this work for me