An Alternative PHPXPath Implementation: PHP.XPath

I l @ ve RuBoard

An Alternative PHP/XPath Implementation: PHP.XPath

In the words of its developers, PHP.XPath is ". . . a PHP class for searching an XML document using XPath, and making modifications using a DOM style API . . . [it] does not require the DOM XML PHP library" [1] . The class, which is maintained as an open source project on the SourceForge network (http://www.sourceforge.net) by Nigel Swinson, Sam Blum, and Daniel Allen, is released under the Mozilla Public License, and is freely downloadable from http://www. sourceforge .net/projects/phpxpath.

[1] SourceForge.net. "Project: PHP.XPath Summary." Available from the Internet: http://www.sourceforge.net/projects/phpxpath.

As the previous description suggests, there isn't anything very complicated about the PHP.XPath class. It accepts XML data (either a file or a string) as argument, parses the data, and creates an object representing the XML document. The methods exposed by this object allow developers to create XML nodesets based on XPath expressions; add, edit, and delete nodes from the document tree; and extract character data embedded within specific XML elements. In order to demonstrate how the class works, let's consider a simple example (see Listing 8.5).

Listing 8.5 A simple XML Document ( market.xml )
 <?xml version="1.0"?>  <sentence>  Today in the market, I spy  <vegetable color='green'>cabbages</vegetable>,  <fruit color='red'>apples</fruit>,  <fruit color='green'>pears</fruit>,  <vegetable color='purple'>aubergines</vegetable>, and  <fruit color='orange'>oranges</fruit>  </sentence> 

The Number Game

All the examples in this section use version 2.1 of the PHP.XPath class.

Listing 8.6 demonstrates using the PHP.XPath class to obtain a collection of all the <fruit> elements within the document (via an XPath expression), and print the contents of each of these elements in an HTML list.

Listing 8.6 Extracting a Node Collection from an XML Document with PHP.XPath
 <html>  <head></head>  <body>  The following fruits were encountered in this document:  <ul>  <?php  // include class  require("XPath.class.php");  /*  the first step is to instantiate an object of the class  the constructor accepts the name of an XML file as argument;  it then parses this XML file and creates a context for subsequent XPath queries  */  $xpath = new XPath("market.xml");  /*  next, retrieve a collection of <fruit> nodes  the match() method accepts an XPath expression as argument,  and returns a node collection matching that expression, as an array  */  $nodeCollection = $xpath->match("//fruit");  // want to see what it looks like?  // uncomment the following line  // print_r($nodeCollection);  /*  finally, iterate through the returned node collection  and print the content of each node  the getData() method returns the content (character data)  of a particular node  */  foreach($nodeCollection as $node)  {       echo  "<li>" . $xpath->getData($node);  }  ?>  </ul>  </body>  </html> 

The PHP.XPath class exposes a number of different methods; however, the two you're likely to use most often are the match() and getData() methods. The match() method evaluates a specific XPath expression within the context of the selected XML document and returns an array of nodes matching the expression; whereas the getData() method extracts the content, or character data, of a specified node.

With this fundamental understanding in place, it's possible to use the PHP.XPath class for even more complex operations. In order to illustrate this, I will rewrite the data tabulation program first seen in Listing 3.12, using the PHP.XPath class instead of PHP's native DOM and XPath functions. Listing 8.7 contains the XML source, which needs to be collated, averaged, and presented in a 2x2 table.

Listing 8.7 A Compilation of Experiment Readings ( data.xml )
 <?xml version="1.0"?>  <project id="49">       <!-- data for 3 cultures: Alpha, Beta and Gamma, tested at temperatures ranging from graphics/ccc.gif 10C to 50C -->       <!-- readings indicate cell counts 4 hours after start of experiment -->       <record>            <culture>Alpha</culture>            <temperature>10</temperature>            <reading>25000</reading>       </record>       <record>            <culture>Beta</culture>            <temperature>10</temperature>            <reading>4000</reading>       </record>       <record>            <culture>Alpha</culture>            <temperature>10</temperature>              <reading>23494</reading>       </record>       <record>            <culture>Alpha</culture>            <temperature>20</temperature>            <reading>21099</reading>       </record>       <record>            <culture>Gamma</culture>            <temperature>40</temperature>            <reading>768</reading>       </record>       <record>            <culture>Gamma</culture>            <temperature>10</temperature>            <reading>900</reading>       </record>       <!-- snip -->  </project> 

Listing 8.8 has the code that actually does all the work.

Listing 8.8 Averaging and Tabulating Experiment Readings with PHP.XPath
 <html>  <head>  <basefont face="Arial">  </head>  <body bgcolor="white">  <?php  // include class definition  require("XPath.class.php");  // XML file  $xml_file = "data.xml";  // create arrays to hold culture/temperature list  $cultures = array();  $temperatures = array();  // create XPath object  $xpath = new XPath($xml_file);  // get a list of "culture" nodes  $nodeset = $xpath->match("//culture");  // ...and create an array containing  // the names of all available cultures  for ($x=0; $x<sizeof($nodeset); $x++)  {      $cultures[] = $xpath->getData($nodeset[$x]);  }  // strip out duplicates  $cultures = array_unique($cultures);  // do the same thing for temperature points  $nodeset = $xpath->match("//temperature");  for ($x=0; $x<sizeof($nodeset); $x++)  {      $temperatures[] = $xpath->getData($nodeset[$x]);  }  $temperatures = array_unique($temperatures);  // sort both arrays  natsort($temperatures);  natsort($cultures);  ?>  <table border="1" cellspacing="5" cellpadding="5">  <tr>  <td>&nbsp;</td>  <?php  // first row of table, print culture names  foreach($cultures as $c)  {      echo "<td>$c</td>";  }  ?>  </tr>  <?php  foreach($temperatures as $t)  {      // create as many rows as there are temperature points       echo "<tr>";       echo "<td>$t</td>";       // for each intersection (culture, temperature)       // print average of available readings       foreach($cultures as $c)       {             echo "<td>" . intersection($t, $c) . "</td>";       }       echo "</tr>";  }  ?>  </table>  <?php  // this function collects all readings for  // a particular culture/temperature  // totals them and averages them  function intersection($temperature, $culture)  {       // get a reference to the XPath object        global $xpath;        // set up variables to hold total and frequency        $total = 0;        $count = 0;        // get a list of "reading" nodes        // for records with culture c and temperature t        $nodeset = $xpath->match("//record[culture='" . $culture . "' and temperature='" . graphics/ccc.gif $temperature . "']/reading");        // iterate through nodeset        // add the readings        foreach ($nodeset as $reading)        {             $total += $xpath->getData($reading);              $count++;        }        // and then average them        if ($count > 0)        {             return $total/$count;        }        return 0;  }  ?>  </body>  </html> 

Listing 8.8 uses three different XPath expressions. The first two are used to create a list of available cultures and temperature points (they are required for the row and column headings of the table), whereas the third XPath returns a list of nodes matching a specific culture and temperature. With all this in place, all that's left is to add the readings associated with each of these nodes to reach a total number, and divide that total number by the number of nodes (readings) to obtain an average cell count.

Again, most of the work here is done by the match() and getData() methods, which make it possible to easily create subsets of XML elements matching a specific criteria, and retrieve the data contained within them.

This is just one example of many. The PHP.XPath class comes with a remarkably full-featured API, which opens up numerous possibilities to the creative developer. Examples and documentation are available at the official web site for the project (http://www.sourceforge.net/projects/phpxpath), together with introductory material to get you started.

Plug In, Click Through

Drop by this book's companion web site for links to other open source XML/PHP alternatives.

I l @ ve RuBoard


XML and PHP
XML and PHP
ISBN: 0735712271
EAN: 2147483647
Year: 2002
Pages: 84

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