Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pulling both the text and attribute of a given node using Xpath

Tags:

dom

php

xpath

I'm parsing XML results from an API call using PHP and xpath.

 $dom = new DOMDocument();
 $dom->loadXML($response->getBody());

 $xpath = new DOMXPath($dom);
 $xpath->registerNamespace("a", "http://www.example.com");

 $hrefs = $xpath->query('//a:Books/text()', $dom);

 for ($i = 0; $i < $hrefs->length; $i++) {
      $arrBookTitle[$i] = $hrefs->item($i)->data;
 }

 $hrefs = $xpath->query('//a:Books', $dom);

 for ($i = 0; $i < $hrefs->length; $i++) {
      $arrBookDewey[$i] = $hrefs->item($i)->getAttribute('DeweyDecimal');
 }

This works but is there a way I can access both the text and the attribute from one query? And if so how do you get to those items once query is executed?

like image 862
Scott Gottreu Avatar asked Sep 26 '08 20:09

Scott Gottreu


2 Answers

After doing some looking around I came across this solution. This way I can get the element text and access any attributes of the node.

$hrefs = $xpath->query('//a:Books', $dom);

for ($i = 0; $i < $hrefs->length; $i++) {
    $arrBookTitle[$i] = $hrefs->item($i)->nodeValue;
    $arrBookDewey[$i] = $hrefs->item($i)->getAttribute('DeweyDecimal');
}
like image 172
Scott Gottreu Avatar answered Oct 09 '22 09:10

Scott Gottreu


One single XPath expression that will select both the text nodes of "a:Books" and their "DeweyDecimal" attribute, is the following

//a:Books/text() | //a:Books/@DeweyDecimal

Do note the use of the XPath's union operator in the expression above.

Another note: try to avoid using the "//" abbreviation as it may cause the whole XML document to be traversed and thus is very expensive. It is recommended to use a more specific XPath expression (such as consisting of a chain of specific location steps) always when the structure of the XML document is known.

like image 24
Dimitre Novatchev Avatar answered Oct 09 '22 11:10

Dimitre Novatchev