12.6.1. ProblemYou want to make sophisticated queries of your XML data without parsing the document node by node. 12.6.2. SolutionUse 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. DiscussionExcept 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
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
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
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
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
Since the inner XPath queries return only one element, use list to grab it from the array. 12.6.4. See AlsoDocumentation 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. |