Recipe 12.6. Extracting Information Using XPath


12.6.1. Problem

You want to make sophisticated queries of your XML data without parsing the document node by node.

12.6.2. Solution

Use XPath.

XPath is available in SimpleXML:

<?php $s = simplexml_load_file('address-book.xml'); $emails = $s->xpath('/address-book/person/email'); foreach ($emails as $email) {     // do something with $email } ?>

And in DOM:

<?php $dom = new DOMDocument; $dom->load('address-book.xml'); $xpath = new DOMXPath($dom); $email = $xpath->query('/address-book/person/email'); foreach ($emails as $email) {     // do something with $email } ?>

12.6.3. Discussion

Except for the simplest documents, it's rarely easy to access the data you want one element at a time. As your XML files become increasingly complex and your parsing desires grow, using XPath is easier than filtering the data inside a foreach.

PHP has an XPath class that takes a DOM object as its constructor. You can then search the object and receive DOM nodes in reply. SimpleXML also supports XPath, and it's easier to use because it's integrated into the SimpleXML object.

DOM supports XPath queries, but you do not perform the query directly on the DOM object itself. Instead, you create a DOMXPath object, as shown in Example 12-9.

Using XPath and DOM

$dom = new DOMDocument; $dom->load('address-book.xml'); $xpath = new DOMXPath($dom); $email = $xpath->query('/address-book/person/email');

Instantiate DOMXPath by passing in a DOMDocument to the constructor. To execute the XPath query, call query( ) with the query text as your argument. This returns an iterable DOM node list of matching nodes (see Example 12-10).

Using XPath with DOM in a basic example

$dom = new DOMDocument; $dom->load('address-book.xml'); $xpath = new DOMXPath($dom); $emails = $xpath->query('/address-book/person/email'); foreach ($emails as $e) {     $email = $e->firstChild->nodeValue;     // do something with $email }

After creating a new DOMXPath object, query this object using DOMXPath::query( ), passing the XPath query as the first parameter (in this example, it's /people/person/email). This function returns a node list of matching DOM nodes.

By default, DOMXPath::query( ) operates on the entire XML document. Search a subsection of the tree by passing in the subtree as a final parameter to query( ). For instance, to gather all the first and last names of people in the address book, retrieve all the people nodes and query each node individually, as shown in Example 12-11.

Using XPath with DOM in a more complicated example

$dom = new DOMDocument; $dom->load('address-book.xml'); $xpath = new DOMXPath($dom); $person = $xpath->query('/address-book/person'); foreach ($person as $p) {     $fn = $xpath->query('firstname', $p);     $firstname = $fn->item(0)->firstChild->nodeValue;     $ln = $xpath->query('lastname', $p);     $lastname = $ln->item(0)->firstChild->nodeValue;     print "$firstname $lastname\n"; } David Sklar Adam Trachtenberg

Inside the foreach, call DOMXPath::query( ) to retrieve the firstname and lastname nodes. Now, in addition to the XPath query, also pass $p to the method. This makes the search local to the node.

In contrast to DOM, all SimpleXML objects have an integrated xpath( ) method. Calling this method queries the current object using XPath and returns a SimpleXML object containing the matching nodes, so you don't need to instantiate another object to use XPath. The method's one argument is your XPath query.

Use Example 12-12 to find all the matching email addresses in the sample address book.

Using XPath and SimpleXML in a basic example

$s = simplexml_load_file('address-book.xml'); $emails = $s->xpath('/address-book/person/email'); foreach ($emails as $email) {     // do something with $email }

This is shorter because there's no need to dereference the firstNode or to take the nodeValue.

SimpleXML handles the more complicated example, too. Since xpath( ) returns SimpleXML objects, you can query them directly, as in Example 12-13.

Using XPath with SimpleXML in a more complicated example

$s = simplexml_load_file('address-book.xml'); $people = $s->xpath('/address-book/person'); foreach($people as $p) {     list($firstname) = $p->xpath('firstname');     list($lastname) = $p->xpath('lastname');     print "$firstname $lastname\n"; } David Sklar Adam Trachtenberg

Since the inner XPath queries return only one element, use list to grab it from the array.

12.6.4. See Also

Documentation on DOM XPath at http://www.php.net/function.dom-domxpath-construct.php; the offical XPath specification at http://www.w3.org/TR/xpath; the XPath chapter from XML in a Nutshell at http://www.oreilly.com/catalog/xmlnut/chapter/ch09.html.




PHP Cookbook, 2nd Edition
PHP Cookbook: Solutions and Examples for PHP Programmers
ISBN: 0596101015
EAN: 2147483647
Year: 2006
Pages: 445

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net