Source for file result.php
Documentation is available at result.php
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2001 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Dan Allen <dan@mojavelinux.com> |
// +----------------------------------------------------------------------+
// $Id: result.php,v 1.15 2005/10/12 14:48:55 toggg Exp $
// Result class for the Xpath/DOM XML manipulation and query interface.
define('XML_XPATH_SORT_TEXT_ASCENDING', 1 );
define('XML_XPATH_SORT_NUMBER_ASCENDING', 2 );
define('XML_XPATH_SORT_NATURAL_ASCENDING', 3 );
define('XML_XPATH_SORT_TEXT_DESCENDING', 4 );
define('XML_XPATH_SORT_NUMBER_DESCENDING', 5 );
define('XML_XPATH_SORT_NATURAL_DESCENDING', 6 );
// {{{ class XML_XPath_result
* Interface for an XML_XPath result so that one can cycle through the result set and manipulate
* the main tree with DOM methods using a seperate pointer then the original class.
* @author Dan Allen <dan@mojavelinux.com>
* original xpath query, stored when we need to sort
* determines if we have counted the first node of the result nodeset
* @var boolean $isRewound
* The type of result that the query generated
* either array of nodesets, string, boolean or number from xpath/DOM query
* xpath context object for the current domxml object
* domxml object, need for many common functions
$this->query = $in_query;
// move the pointer to the first node if at least one node in the result exists
// for convience, just so we don't have to call nextNode() if we expect only one
* Return the data from the xpath query. This function will be used mostly for xpath
* queries that result in scalar results, but in the case of nodesets, returns size
* @return mixed scalar result from xpath query or size of nodeset
return $this->data ? true : false;
* Retrieve the type of result that was returned by the xpath query.
* @return int code corresponding to the xpath result types constants
* Return the number of nodes if the result is a nodeset or 1 for scalar results.
* result (boolean, string, numeric) xpath queries
* @return int number of results returned by xpath query
* Return the index of the result nodeset.
* @return int current index of the result nodeset
* Sort the nodeset in this result. The sort can be either ascending or descending, and
* the comparisons can be text, number or natural (see the constants above). The sort
* axis is provided as an xpath query and is the location path relative to the node given.
* For example, so sort on an attribute, you would provide '@foo' and it will look at the
* attribute for each node.
* NOTE: If the axis is not found, the node will comes first in the sort order for ascending
* order and at the end for descending orde.
* @param string $in_sortXpath relative xpath query location to each node in nodeset
* @param int $in_order either XML_XPATH_SORT_TEXT_[DE|A]SCENDING,
* XML_XPATH_SORT_NUMBER_[DE|A]SCENDING,
* XML_XPATH_SORT_NATURAL_[DE|A]SCENDING
* @return boolean success (return false if nothing to sort)
function sort($in_sortXpath = '.', $in_order = XML_XPATH_SORT_TEXT_ASCENDING , $in_permanent = false )
// make sure we are dealing with a result that is a nodeset
// we don't need to run it again if we are soring on the current node values
if ($in_sortXpath == '' || $in_sortXpath == '.') {
foreach ($this->data as $index => $node) {
$data[] = $node->get_content ();
// we need to run the query again
// we never actually ran the query, but we can rebuild it...and we will do that now
// this is for DOM queries, such as childNodes() and getElementsByTagName()
// here I am reissuing the query, but with the sort path appended followed by the
// node in a logical 'OR'. The trick here is that I can keep the original nodes
// in sorted order and then just weed out the nodes I used to sort.
$xpathResult = @$this->ctx->xpath_eval ($this->query . '/' . $in_sortXpath . '|' . $this->query);
if (!$xpathResult || empty ($xpathResult->nodeset )) {
// The reason we did a double query is so that we could line up the original nodes
// with the original data set, fill in any parts of the sorted nodeset that have
// missing sort nodes, sort the sorted nodeset and then reindex the original data array
while(isset($this->data[$origIndex])) {
// make sure we are lined up on original nodes, then we can proceed to check
// the next node in each nodeset to determine of the sort node was found
if ($this->data[$origIndex] == $xpathResult->nodeset [$sortIndex]) {
// make sure we have not advanced beyond the end of the sort nodeset
if (isset($xpathResult->nodeset [$sortIndex])) {
// if the values of the next two indices of the sort nodeset and the
// original nodeset are the same, we had a missing node
if (isset($this->data[$origIndex]) && $this->data[$origIndex] == $xpathResult->nodeset [$sortIndex]) {
// okay, they were different, we found a sort node, get its value
$data[] = $xpathResult->nodeset [$sortIndex]->get_content ();
// the last sort nodeset element is missing, which means the sort nodeset
// was missing the last sort node
case XML_XPATH_SORT_TEXT_ASCENDING:
asort($data, SORT_STRING);
case XML_XPATH_SORT_NUMBER_ASCENDING:
asort($data, SORT_NUMERIC);
case XML_XPATH_SORT_NATURAL_ASCENDING:
case XML_XPATH_SORT_TEXT_DESCENDING:
arsort($data, SORT_STRING);
case XML_XPATH_SORT_NUMBER_DESCENDING:
arsort($data, SORT_NUMERIC);
case XML_XPATH_SORT_NATURAL_DESCENDING:
$data = array_reverse($data, true);
$dataReordered = array();
// this is NOT just array_values, we need to use the keys to put the values
foreach ($data as $reindex => $value) {
$dataReordered[] = $this->data[$reindex];
$this->data = $dataReordered;
// if this is a permanent sort, make the change to the main tree
if ($in_permanent && $parent = $this->data[0]->parent_node()) {
// nix all the children by overwriting node and fixing attributes
$attributes = $parent->has_attributes() ? $parent->attributes() : array();
$parent->replace_node($clone = $parent->clone_node());
foreach($attributes as $attributeNode) {
// waiting on set_attribute_node() to work here
$parent->set_attribute($attributeNode->node_name(), $attributeNode->value());
foreach ($this->data as $key => $sortedNode) {
$this->data[$key] = $parent->append_child($sortedNode);
// rewind to the beginning of the data set
* Reset the result index back to the beginning, if this is an XPATH_NODESET
* @return boolean success
if (is_array($this->data)) {
* Move to the next node in the nodeset of results. This can be used inside of a
* while loop, so that it is possible to step through the nodes one by one.
* It is important to note that the first call to next will put the pointer at
* the first index and not the second...this is just a more convenient way of
* handling the logic. If you rewind() the data and then call next() as the conditional
* on a while loop, you can work through each of the results from the first to the last.
* @return boolean success node found and pointer advanced
if (is_array($this->data)) {
if ($node = $seekFunction($this->data)) {
// {{{ boolean nextByNodeName()
* Move to the next node in the nodeset of results where the node has the name provided.
* This can be used inside of a while loop, so that it is possible to step through the
* @param string $in_name name of node to find
* @return boolean next node existed and pointer moved
if (($node = reset($this->data)) && $node->node_name() == $in_name) {
if ($node->node_name() == $in_name) {
// {{{ boolean nextByNodeType()
* Move to the next node in the nodeset of results where the node has the type provided.
* This can be used inside of a while loop, so that it is possible to step through the
* @param int $in_type type of node to find
* @return boolean next node existed and pointer moved
if (($node = reset($this->data)) && $node->node_type() == $in_type) {
if ($node->node_type() == $in_type) {
* Retrieve current pointer
* If the result is a nodeset (which is the most common use of the result object) than
* this function returns the current pointer in the result array.
* @return object XML_XPath pointer
* Move to last result node, if this is an XPATH_NODESET
* @return boolean success
* Free the result object in order to save memory.
Documentation generated on Mon, 11 Mar 2019 14:44:42 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|