cvs: pear /XML_XPath TODO XPath.php package.xml /XML_XPath/XPath common.php error.php result.php
| From: | Daniel Allen | Date: | Fri, 24 May 2002 05:05:16 +0000 |
| Subject: | cvs: pear /XML_XPath TODO XPath.php package.xml /XML_XPath/XPath common.php error.php result.php | ||
| Groups: | php.pear.cvs | ||
| Request: | Send a blank email to pear-cvs+get-4069@lists.php.net to get a copy of this message | ||
dallen Fri May 24 01:05:16 2002 EDT
Modified files:
/pear/XML_XPath TODO XPath.php package.xml
/pear/XML_XPath/XPath common.php error.php result.php
Log:
- Changed function names and prefixes from XPath to XML_XPath
- updated new function names for domxml extension
- lots of bugfixes
Index: pear/XML_XPath/TODO diff -u pear/XML_XPath/TODO:1.1 pear/XML_XPath/TODO:1.2 --- pear/XML_XPath/TODO:1.1 Fri Mar 15 03:38:34 2002 +++ pear/XML_XPath/TODO Fri May 24 01:05:16 2002 @@ -9,14 +9,18 @@ Status Description =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - [*] A more formal and informative interface to the load() function + [@] implement siblingNode and childNode to get a tag by name + [@] sort for results + + [@] A more formal and informative interface to the load() function, used 'file/string/object' + + [@] prevent duplicate root in appendChild() + [*] make an example.php and example.out for people to read through [*] make a short test harness just so I know I don't commit bad shit - [@] prevent duplicate root in appendChild() - [*] finally figured out substitute entities default, so see if we can make this usable in the class @@ -24,5 +28,3 @@ now [*] considering doing substringData for attribute nodes...just seems to make sense - - [@] sort for results Index: pear/XML_XPath/XPath.php diff -u pear/XML_XPath/XPath.php:1.7 pear/XML_XPath/XPath.php:1.8 --- pear/XML_XPath/XPath.php:1.7 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath.php Fri May 24 01:05:16 2002 @@ -4,7 +4,7 @@ // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ -// | Copyright (c) 1997-2001 The PHP Group | +// | Copyright (c) 1997-2002 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 | @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: XPath.php,v 1.7 2002/03/16 09:14:27 dallen Exp $ +// $Id: XPath.php,v 1.8 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -28,52 +28,52 @@ // {{{ error codes /* - * Error codes for the XPath interface, which will be mapped to textual messages - * in the XPath::errorMessage() function. If you are to add a new error code, be - * sure to add the textual messages to the XPath::errorMessage() function as well + * Error codes for the XML_XPath interface, which will be mapped to textual messages + * in the XML_XPath::errorMessage() function. If you are to add a new error code, be + * sure to add the textual messages to the XML_XPath::errorMessage() function as well */ -define("XPATH_OK", 1); -define("XPATH_ERROR", -1); -define("XPATH_ALREADY_EXISTS", -2); -define("XPATH_INVALID_DOCUMENT", -3); -define("XPATH_INVALID_QUERY", -4); -define("XPATH_NO_DOM", -5); -define("XPATH_INVALID_INDEX", -6); -define("XPATH_INVALID_NODESET", -7); -define("XPATH_NOT_LOADED", -8); -define("XPATH_INVALID_NODETYPE", -9); -define("XPATH_FILE_NOT_WRITABLE", -10); -define("XPATH_NODE_REQUIRED", -11); -define("XPATH_INDEX_SIZE", -12); -define("XML_PARSE_ERROR", -13); -define("XML_DUPLICATE_ROOT", -14); +define('XML_XPATH_OK', 1); +define('XML_XPATH_ERROR', -1); +define('XML_XPATH_ALREADY_EXISTS', -2); +define('XML_XPATH_INVALID_DOCUMENT', -3); +define('XML_XPATH_INVALID_QUERY', -4); +define('XML_XPATH_NO_DOM', -5); +define('XML_XPATH_INVALID_INDEX', -6); +define('XML_XPATH_INVALID_NODESET', -7); +define('XML_XPATH_NOT_LOADED', -8); +define('XML_XPATH_INVALID_NODETYPE', -9); +define('XML_XPATH_FILE_NOT_WRITABLE', -10); +define('XML_XPATH_NODE_REQUIRED', -11); +define('XML_XPATH_INDEX_SIZE', -12); +define('XML_PARSE_ERROR', -13); +define('XML_DUPLICATE_ROOT', -14); // }}} // {{{ includes -require_once "PEAR.php"; -require_once "XPath/common.php"; -require_once "XPath/result.php"; -require_once "XPath/error.php"; +require_once 'PEAR.php'; +require_once 'XPath/common.php'; +require_once 'XPath/result.php'; +require_once 'XPath/error.php'; // }}} -// {{{ class XPath +// {{{ class XML_XPath /** - * The main "XPath" class is simply a container class with some methods for + * The main "XML_XPath" class is simply a container class with some methods for * creating DOM xml objects and preparing error codes * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath extends XPath_common { +class XML_XPath extends XML_XPath_common { // {{{ properties /** @var object xml data object */ @@ -91,12 +91,12 @@ // }}} // {{{ constructor - function Xpath($in_xml = null) + function XML_Xpath($in_xml = null, $in_type = 'string') { // load the xml document if passed in here // if not defined, require load() to be called if (!is_null($in_xml)) { - if(XPath::isError($result = $this->load($in_xml))) { + if (XML_XPath::isError($result = $this->load($in_xml, $in_type))) { $this = $result; } } @@ -114,40 +114,40 @@ * @param mixed $in_xml xml document, in one of 3 forms (object, string or file) * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ - function load($in_xml) + function load($in_xml, $in_type = 'string') { // if we already have a document loaded, then throw a warning if ($this->loaded) { - return PEAR::raiseError(null, XPATH_ALREADY_EXISTS, null, E_USER_WARNING, $this->xml->root(), 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_ALREADY_EXISTS, null, E_USER_WARNING, $this->xml->root(), 'XML_XPath_Error', true); } // in this case, we already have an xmldom object - if (is_class_type($in_xml, 'domdocument')) { + if ($in_type == 'object' && get_class($in_xml) == 'DomDocument') { $this->xml = $in_xml; } // we can read the file, so use xmldocfile to make a xmldom object - elseif(file_exists($in_xml) && is_readable($in_xml)) { - $this->xml = @xmldocfile($in_xml); + elseif ($in_type == 'file' && @file_exists($in_xml)) { + $this->xml = @domxml_open_file($in_xml); } // this is a string, so attempt to make an xmldom object from string - elseif(is_string($in_xml)) { - $this->xml = @xmldoc($in_xml); + elseif($in_type == 'string' && is_string($in_xml)) { + $this->xml = @domxml_open_mem($in_xml); } // not a valid xml instance, so throw error else { - return PEAR::raiseError(null, XPATH_INVALID_DOCUMENT, null, E_USER_ERROR, "The xml data '$in_xml' could not be parsed to xml dom", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_DOCUMENT, null, E_USER_ERROR, "The xml data '$in_xml' could not be parsed to xml dom", 'XML_XPath_Error', true); } - // make sure a xmldom object was created, and if so initialized the state - if (is_class_type($this->xml, 'domdocument')) { + // make sure a domxml object was created, and if so initialized the state + if (get_class($this->xml) == 'DomDocument') { $this->loaded = true; $this->ctx = $this->xml->xpath_new_context(); $this->pointer = $this->xml->root(); return true; } - // we could not make a xmldom object, so throw an error + // we could not make a domxml object, so throw an error else { - return PEAR::raiseError(null, XPATH_NO_DOM, null, E_USER_ERROR, "A DomDocument could not be instantiated from '$in_xml'", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_NO_DOM, null, E_USER_ERROR, "A DomDocument could not be instantiated from '$in_xml'", 'XML_XPath_Error', true); } } @@ -162,12 +162,12 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return mixed number of nodes or value of scalar result {or XPath_Error exception} + * @return mixed number of nodes or value of scalar result {or XML_XPath_Error exception} */ function getOne($in_xpathQuery, $in_movePointer = false) { // Execute the xpath query and return the results, then reset the result index - if (XPath::isError($result = $this->evaluate($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->evaluate($in_xpathQuery, $in_movePointer))) { return $result; } return $result->getData(); @@ -177,25 +177,25 @@ // {{{ void evaluate() /** - * Evaluate the xpath expression on the loaded xml document. An XPath_Result object is + * Evaluate the xpath expression on the loaded xml document. An XML_XPath_Result object is * returned which can be used to manipulate the results * * @param string $in_xpathQuery xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return object result object {or XML_XPath_Error exception} */ function evaluate($in_xpathQuery, $in_movePointer = false) { // Make sure we have loaded an xml document and were able to create an xpath context - if (!is_class_type($this->ctx, 'xpathcontext')) { - return PEAR::raiseError(null, XPATH_NOT_LOADED, null, E_USER_ERROR, null, 'XPath_Error', true); + if (!is_a_php_class($this->ctx, 'xpathcontext')) { + return PEAR::raiseError(null, XML_XPATH_NOT_LOADED, null, E_USER_ERROR, null, 'XML_XPath_Error', true); } if (!$result = @xpath_eval($this->ctx, $in_xpathQuery)) { - return PEAR::raiseError(null, XPATH_INVALID_QUERY, null, E_USER_WARNING, "XPath query: $in_xpathQuery", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_QUERY, null, E_USER_WARNING, "XML_XPath query: $in_xpathQuery", 'XML_XPath_Error', true); } - $resultObj = new XPath_result($result, $in_xpathQuery, $this->xml, $this->ctx); + $resultObj = new XML_XPath_result($result, $in_xpathQuery, $this->xml, $this->ctx); if ($in_movePointer && $resultObj->resultType() == XPATH_NODESET && $resultObj->numResults()) { $this->setPointer($resultObj->getPointer()); @@ -207,7 +207,7 @@ // {{{ boolean isError() /** - * Tell whether a result code from a XPath method is an error. + * Tell whether a result code from a XML_XPath method is an error. * * @param object $in_value object in question * @@ -216,14 +216,14 @@ */ function isError($in_value) { - return is_class_type($in_value, 'xpath_error'); + return is_a($in_value, 'xml_xpath_error'); } // }}} // {{{ mixed errorMessage() /** - * Return a textual error message for an XPath error code. + * Return a textual error message for an XML_XPath error code. * * @param int $in_value error code * @@ -238,31 +238,31 @@ // define the varies error messages if (!isset($errorMessages)) { $errorMessages = array( - XPATH_OK => 'no error', - XPATH_ERROR => 'unknown error', - XPATH_ALREADY_EXISTS => 'xml document already loaded', - XPATH_INVALID_DOCUMENT => 'invalid xml document', - XPATH_INVALID_QUERY => 'invalid xpath query', - XPATH_NO_DOM => 'DomDocument could not be instantiated', - XPATH_INVALID_INDEX => 'invalid index', - XPATH_INVALID_NODESET => 'requires nodeset and one of appropriate type', - XPATH_NOT_LOADED => 'DomDocument has not been loaded', - XPATH_INVALID_NODETYPE => 'invalid nodetype for requested feature', - XPATH_FILE_NOT_WRITABLE => 'file could not be written', - XPATH_NODE_REQUIRED => 'DomNode required for operation', - XPATH_INDEX_SIZE => 'index given out of range', + XML_XPATH_OK => 'no error', + XML_XPATH_ERROR => 'unknown error', + XML_XPATH_ALREADY_EXISTS => 'xml document already loaded', + XML_XPATH_INVALID_DOCUMENT => 'invalid xml document', + XML_XPATH_INVALID_QUERY => 'invalid xpath query', + XML_XPATH_NO_DOM => 'DomDocument could not be instantiated', + XML_XPATH_INVALID_INDEX => 'invalid index', + XML_XPATH_INVALID_NODESET => 'requires nodeset and one of appropriate type', + XML_XPATH_NOT_LOADED => 'DomDocument has not been loaded', + XML_XPATH_INVALID_NODETYPE => 'invalid nodetype for requested feature', + XML_XPATH_FILE_NOT_WRITABLE => 'file could not be written', + XML_XPATH_NODE_REQUIRED => 'DomNode required for operation', + XML_XPATH_INDEX_SIZE => 'index given out of range', XML_PARSE_ERROR => 'parse error in xml string', XML_DUPLICATE_ROOT => 'root element already exists' ); } // If this is an error object, then grab the corresponding error code - if (XPath::isError($in_value)) { + if (XML_XPath::isError($in_value)) { $in_value = $in_value->getCode(); } // return the textual error message corresponding to the code - return isset($errorMessages[$in_value]) ? $errorMessages[$in_value] : $errorMessages[XPATH_ERROR]; + return isset($errorMessages[$in_value]) ? $errorMessages[$in_value] : $errorMessages[XML_XPATH_ERROR]; } // }}} Index: pear/XML_XPath/package.xml diff -u pear/XML_XPath/package.xml:1.3 pear/XML_XPath/package.xml:1.4 --- pear/XML_XPath/package.xml:1.3 Mon Apr 1 07:13:59 2002 +++ pear/XML_XPath/package.xml Fri May 24 01:05:16 2002 @@ -23,13 +23,13 @@ </maintainer> </maintainers> <deps> - <dep type="php" rel="ge" version="4.2.0" /> + <dep type="php" rel="ge" version="4.2.1" /> </deps> <release> <license>PHP 2.01</license> <state>beta</state> - <version>1.1</version> - <date>2002-03-10</date> + <version>1.0</version> + <date>2002-05-23</date> <notes> This is the initial independent PEAR release. </notes> Index: pear/XML_XPath/XPath/common.php diff -u pear/XML_XPath/XPath/common.php:1.11 pear/XML_XPath/XPath/common.php:1.12 --- pear/XML_XPath/XPath/common.php:1.11 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath/common.php Fri May 24 01:05:16 2002 @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: common.php,v 1.11 2002/03/16 09:14:27 dallen Exp $ +// $Id: common.php,v 1.12 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -28,7 +28,9 @@ // {{{ functions /** - * is_a is only defined in php CVS, so I implemented its functionality for the time being + * is_a is only defined in php for user functions, + * so I implemented its functionality for php objects + * until they fix (or never fix) this problem * * @param object $class the class to check * @param string $match class name you are looking for @@ -36,24 +38,33 @@ * @access public * @return boolean whether the class is of the class type or a descendent of the class */ -function is_class_type($class, $match) +function is_a_php_class($class, $match) { if (empty($class)) { return false; } + $class = is_object($class) ? get_class($class) : $class; if (strtolower($class) == strtolower($match)) { return true; } - return is_class_type(get_parent_class($class), $match); + + return is_a_php_class(get_parent_class($class), $match); } // }}} - -// {{{ class XPath_common +/** + * changes to domxml that I have to look at + * + * implement the striping of formating on the way in possibly + * append_sibling() added + * insert_before() now copies node before inserting + * domxml_parser() might be good for bringing in stuff + */ +// {{{ class XML_XPath_common /** - * The XPath_common class contains the DOM functions used to manipulate + * The XML_XPath_common class contains the DOM functions used to manipulate * and maneuver through the xml tree. The main thing to understand is * that all operations work around a single pointer. This pointer is your * place holder within the document. Each function you run assumes the @@ -64,33 +75,35 @@ * prepares the pointer to the requested location in the tree if an xpath query * or pointer object is provided. In addition, the init() function checks to * see that the node type is acceptable for the method, and if not throws an - * XPath_Error exception. + * XML_XPath_Error exception. If you want to execute a function and then remain + * in the location of your query, then you specify that you want to move the pointer. + * For the DOM step functions, this is the default action. * * Note: All offsets in the CharacterData interface start from 0. * - * The object model of XPath is as follows (indentation means inheritance): + * The object model of XML_XPath is as follows (indentation means inheritance): * - * XPath_common The main functionality of the XPath class is here. This + * XML_XPath_common The main functionality of the XML_XPath class is here. This * | holds all the DOM functions for manipulating and maneuvering * | through the DOM tree. * | - * +-XPath The frontend for the XPath implementation. Provides default + * +-XML_XPath The frontend for the XML_XPath implementation. Provides default * | functions for preparing the main document, running xpath queries * | and handling errorMessages. * | - * +-Result Extended from the XPath_common class, this object is returned when + * +-Result Extended from the XML_XPath_common class, this object is returned when * an xpath query is executed and can be used to cycle through the * result nodeset or data * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath_common { +class XML_XPath_common { // {{{ properties /** @var object current location in xml document */ @@ -115,15 +128,20 @@ * @param boolean $in_movePointer (optional) move internal pointer with quick xpath query * * @access public - * @return string name of node corresponding to DOM recommendation {or XPath_Error exception} + * @return string name of node corresponding to DOM recommendation {or XML_XPath_Error exception} */ function nodeName($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (!is_null($in_xpathQuery) && XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } + $nodeName = $this->pointer->node_name(); - $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); + + if (!is_null($in_xpathQuery)) { + $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); + } + return $nodeName; } @@ -137,11 +155,11 @@ * @param boolean $in_movePointer (optional) move internal pointer with quick xpath query * * @access public - * @return int DOM type of the node {or XPath_Error exception} + * @return int DOM type of the node {or XML_XPath_Error exception} */ function nodeType($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } $nodeType = $this->pointer->node_type(); @@ -162,7 +180,7 @@ */ function parentNode($in_movePointer = true) { - $parent = $this->pointer->parent(); + $parent = $this->pointer->parent_node(); if ($parent) { if ($in_movePointer) { $this->pointer = $parent; @@ -178,6 +196,115 @@ } // }}} + // {{{ boolean siblingNode() + + /** + * Get the sibling based on the tag name of the sibling. An index can be + * specified which will get the nth sibling with that name. This function uses caching of + * the child array of the parent to speed up multiple uses of it, killing the cache when + * the internal pointer of the parent changes (this can be forced). This is not a DOM + * function, but convienent addition. + * + * @param string $in_name tagname of the sibling node + * @param int $in_index index of the sibling with this tagname (1 based) + * @param boolean $in_movePointer either move the internal pointer or return pointer + * @param boolean $in_clearCache force clear the cache of the siblings + * + * @access public + * @return boolean if the pointer could be moved, or pointer if $in_movePointer is false + */ + function siblingNode($in_name, $in_index = 1, $in_movePointer = true, $in_clearCache = false) + { + static $nameList, $previousParent; + settype($in_index, 'int'); + $index = $in_index > 0 ? $in_index - 1 : 0; + // if we have changed locations, then reset the child array + $parent = $this->pointer->parent_node(); + if ($parent != $previousParent || $in_clearCache) { + $previousParent = $parent; + $nameList = array(); + } + // if the child array is not set, make it now + // (can be dangerous if DOM changes have occured) + if (empty($nameList)) { + $childNodes = $parent->child_nodes(); + settype($children, 'array'); + foreach ($childNodes as $childNode) { + if ($childNode->is_blank_node() && $this->skipBlanks) { + continue; + } + $nameList[$childNode->node_name()][] = $childNode; + } + } + // either move the pointer or return it + if (isset($nameList[$in_name][$index])) { + if ($in_movePointer) { + $this->pointer = $nameList[$in_name][$index]; + return true; + } + else { + return $nameList[$in_name][$index]; + } + } + else { + return false; + } + } + + // }}} + // {{{ boolean childNode() + + /** + * Get the direct descendant child based on the tag name of the child. An index can be + * specified which will get the nth child with that name. This function uses caching of + * the child array to speed up multiple uses of it, killing the cache when the internal + * pointer changes (this can be forced). This is not a DOM function, but convienent one. + * + * @param string $in_name tagname of the child node + * @param int $in_index index of the sibling with this tagname (1 based) + * @param boolean $in_movePointer either move the internal pointer or return pointer + * @param boolean $in_clearCache force clear the cache of the children + * + * @access public + * @return boolean if the pointer could be moved, or pointer if $in_movePointer is false + */ + function childNode($in_name, $in_index = 1, $in_movePointer = true, $in_clearCache = false) + { + static $nameList, $previousPointer; + settype($in_index, 'int'); + $index = $in_index > 0 ? $in_index - 1 : 0; + // if we have changed locations, then reset the child array + if ($this->pointer != $previousPointer || $in_clearCache) { + $previousPointer = $this->pointer; + $nameList = array(); + } + // if the child array is not set, make it now (can be dangerous) + if (empty($nameList)) { + $childNodes = $this->pointer->child_nodes(); + settype($children, 'array'); + foreach ($childNodes as $childNode) { + if ($childNode->is_blank_node() && $this->skipBlanks) { + continue; + } + $nameList[$childNode->node_name()][] = $childNode; + } + } + // either move the pointer or return it + if (isset($nameList[$in_name][$index])) { + if ($in_movePointer) { + $this->pointer = $nameList[$in_name][$index]; + return true; + } + else { + return $nameList[$in_name][$index]; + } + } + else { + return false; + } + } + + // }}} // {{{ boolean nextSibling() /** @@ -364,59 +491,6 @@ } // }}} - // {{{ boolean getChildByTagName() - - /** - * Get the direct descendant child based on the tag name of the child. An index can be - * specified which will get the nth sibling with that name. This function uses caching of - * the child array to speed up multiple uses of it, killing the cache when the internal - * pointer changes (this can be forced). This is not a DOM function, but convienent one. - * - * @param string $in_name tagname of the child node - * @param int $in_index index of the sibling with this tagname (1 based) - * @param boolean $in_movePointer either move the internal pointer or return pointer - * @param boolean $in_clearCache force clear the cache of the children - * - * @access public - * @return boolean if the pointer could be moved, or pointer if $in_movePointer is false - */ - function getChildByTagName($in_name, $in_index = 1, $in_movePointer = true, $in_clearCache = false) - { - static $nameList, $previousPointer; - settype($in_index, 'int'); - $index = $in_index > 0 ? $in_index - 1 : 0; - // if we have changed locations, then reset the child array - if ($this->pointer != $previousPointer || $in_clearCache) { - $previousPointer = $this->pointer; - $nameList = array(); - } - // if the child array is not set, make it now (can be dangerous) - if (empty($nameList)) { - $childNodes = $this->pointer->children(); - settype($children, 'array'); - foreach ($childNodes as $childNode) { - if ($childNode->is_blank_node() && $this->skipBlanks) { - continue; - } - $nameList[$childNode->node_name()][] = $childNode; - } - } - // either move the pointer or return it - if (isset($nameList[$in_name][$index])) { - if ($in_movePointer) { - $this->pointer = $nameList[$in_name][$index]; - return true; - } - else { - return $nameList[$in_name][$index]; - } - } - else { - return false; - } - } - - // }}} // {{{ boolean isNodeType() /** @@ -427,11 +501,11 @@ * @param boolean $in_movePointer (optional) move internal pointer with quick xpath query * * @access public - * @return boolean same type of node {or XPath_Error exception} + * @return boolean same type of node {or XML_XPath_Error exception} */ function isNodeType($in_type, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } $isNodeType = $this->pointer->node_type() == $in_type ? true : false; @@ -449,11 +523,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return boolean has child nodes {or XPath_Error exception} + * @return boolean has child nodes {or XML_XPath_Error exception} */ function hasChildNodes($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } $hasChildNodes = $this->pointer->has_child_nodes() ? true : false; @@ -471,11 +545,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return boolean attributes exist {or XPath_Error exception} + * @return boolean attributes exist {or XML_XPath_Error exception} */ function hasAttributes($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $hasAttributes = $this->pointer->has_attributes() ? true : false; @@ -495,11 +569,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return boolean existence of attribute {or XPath_Error exception} + * @return boolean existence of attribute {or XML_XPath_Error exception} */ function hasAttribute($in_name, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $hasAttribute = false; @@ -527,11 +601,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return array associative array of attributes {or XPath_Error exception} + * @return array associative array of attributes {or XML_XPath_Error exception} */ function getAttributes($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $return = array(); @@ -550,20 +624,27 @@ /** * Retrieves an attribute value by name from the element node at the current pointer. * + * Grab the attribute value if it exists and return it. If the attribute does not + * exist, this function will return the boolean 'false', so be sure to check properly + * if the value is "" or if the attribute doesn't exist at all. + * * @param string $in_name Name of the attribute * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move the internal pointer with quick xpath query * * @access public - * @return string value of attribute {or XPath_Error exception} + * @return string value of attribute or false if attribute DNE {or XML_XPath_Error exception} */ function getAttribute($in_name, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } + $result = $this->pointer->get_attribute($in_name); + $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); + return $result; } @@ -581,11 +662,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function setAttribute($in_name, $in_value, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $this->pointer->set_attribute($in_name, $in_value); @@ -603,11 +684,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function removeAttribute($in_name, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $this->pointer->remove_attribute($in_name); @@ -629,24 +710,24 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return string substring of the character data {or XPath_Error exception} + * @return string substring of the character data {or XML_XPath_Error exception} */ function substringData($in_offset = 0, $in_count = 0, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_ELEMENT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_ELEMENT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE)))) { return $result; } - if (!is_int($in_offset) || $in_offset < 0 || $in_offset > strlen($this->pointer->get_content())) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XPath_Error', true); + if (!is_int($in_count) || $in_count < 0) { + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XML_XPath_Error', true); } - elseif (!is_int($in_count) || $in_count < 0) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XPath_Error', true); + elseif (!is_int($in_offset) || $in_offset < 0 || $in_offset > strlen($content = $this->pointer->get_content())) { + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XML_XPath_Error', true); } + // if this is an element node, concat all the text children recursively else { - // if this is an element node, concat all the text children recursively - $return = $in_count ? substr($this->pointer->get_content(), $in_offset, $in_count) : - substr($this->pointer->get_content(), $in_offset); + $return = $in_count ? substr($content, $in_offset, $in_count) : + substr($content, $in_offset); } $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); return $return; @@ -664,7 +745,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function insertData($in_content, $in_offset = 0, $in_xpathQuery = null, $in_movePointer = false) { @@ -683,7 +764,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function deleteData($in_offset = 0, $in_count = 0, $in_xpathQuery = null, $in_movePointer = false) { @@ -703,7 +784,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function replaceData($in_content, $in_offset = 0, $in_count = 0, $in_xpathQuery = null, $in_movePointer = false) { @@ -721,7 +802,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function appendData($in_content, $in_xpathQuery = null, $in_movePointer = false) { @@ -729,7 +810,7 @@ } // }}} - // {{{ mixed replaceChild() + // {{{ object replaceChild() /** * Replaces the old child with the new child. If the new child is already in the document, @@ -737,41 +818,39 @@ * all of the nodes are inserted in the location of the old child. * * @param mixed $in_xmlData document fragment or node - * @param boolean $in_returnOriginal (optional) clone the old node and return reference to it * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return object pointer to old node (optional) {or XPath_Error exception} + * @return object pointer to old node {or XML_XPath_Error exception} + * @todo I should make it so an xml_xpath_result is returned or something */ - function replaceChild($in_xmlData, $in_returnOriginal = false, $in_xpathQuery = null, $in_movePointer = false) + function replaceChild($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_CDATA_SECTION_NODE, XML_PI_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_CDATA_SECTION_NODE, XML_PI_NODE)))) { return $result; } - if (XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { + if (XML_XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); return $importedNodes; } - $parent = $this->pointer->parent(); + + $parent = $this->pointer->parent_node(); + $lastNodeIndex = sizeOf($importedNodes) - 1; + // run through all the new nodes...on the last new node, run replace_child() foreach($importedNodes as $index => $importedNode) { - $node = $parent->insert_before($importedNode, $this->pointer); - if ($index == 0) { - $newNode = $node; + if ($index == $lastNodeIndex) { + $oldNode = $parent->replace_child($importedNode, $this->pointer); + } + else { + $parent->insert_before($importedNode, $this->pointer); } } - $oldNode = $this->pointer; - $this->pointer = $newNode; - - // to save memory we only return the original node if requested - $return = $in_returnOriginal ? $oldNode->clone_node(1) : null; - - $oldNode->unlink(); $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return $return; + return $oldNode; } // }}} @@ -786,24 +865,24 @@ * @param boolean $in_movePointer move internal pointer * * @access public - * @return object pointer to the first of the nodes appended {or XPath_Error exception} + * @return object pointer to the first of the nodes appended {or XML_XPath_Error exception} */ function appendChild($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_DOCUMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_DOCUMENT_NODE)))) { return $result; } // if this is a document node, make sure no root exists - if ($this->isNodeType(XML_DOCUMENT_NODE) && $this->xml->root()) { + if ($this->isNodeType(XML_DOCUMENT_NODE) && $this->xml->document_element()) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return PEAR::raiseError(null, XML_DUPLICATE_ROOT, null, E_USER_WARNING, null, 'XPath_Error', true); + return PEAR::raiseError(null, XML_DUPLICATE_ROOT, null, E_USER_WARNING, null, 'XML_XPath_Error', true); } - if (XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { + if (XML_XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { return $importedNodes; } foreach($importedNodes as $index => $importedNode) { - $node = $this->pointer->add_child($importedNode); + $node = $this->pointer->append_child($importedNode); if ($index == 0) { $newNode = $node; } @@ -827,17 +906,17 @@ */ function insertBefore($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } // we do some fance stuff here to make this general...make a fake node $importedNodes = $this->_build_fragment($in_xmlData); - if (XPath::isError($importedNodes)) { + if (XML_XPath::isError($importedNodes)) { return $importedNodes; } - $parent = $this->pointer->parent(); + $parent = $this->pointer->parent_node(); foreach($importedNodes as $index => $importedNode) { $node = $parent->insert_before($importedNode, $this->pointer); if ($index == 0) { @@ -854,33 +933,33 @@ // {{{ object removeChild() /** - * Removes the child node at the current pointer and returns it (optionally). + * Removes the child node at the current pointer and returns it. + * + * This function will remove a child from the list of children and will + * move the pointer to the parent node. * - * @param boolean $in_returnOriginal (optional) return the original node as a clone * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public * @return object cloned node of the removed node, ready to be put in another document - * ??? either put the pointer on the parent or previous sibling, then parent ??? */ - function removeChild($in_returnOriginal = false, $in_xpathQuery = null, $in_movePointer = false) + function removeChild($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_PI_NODE, XML_CDATA_SECTION_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_PI_NODE, XML_CDATA_SECTION_NODE)))) { return $result; } - // if we are returning the removedChild, clone it now - $return = $in_returnOriginal ? $this->pointer->clone_node(1) : null; - // set the node to be removed - $removeNode = $this->pointer; - // set the pointer to the parent (since this node is gone) - $this->pointer = $this->pointer->parent(); - $removeNode->unlink(); + // get the parent + $parent = $this->pointer->parent_node(); + // remove the child + $removedNode = $parent->remove_child($this->pointer); + // set pointer to the parent + $this->pointer = $parent; $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return $return; + return $removedNode; } // }}} @@ -889,40 +968,40 @@ /** * Not in the DOM specification, but certainly a convenient function. Allows you to pass * in an xml document fragment which will be parsed into an xml object and merged into the - * xml document, replacing all the previous children of the node. + * xml document, replacing all the previous children of the node. It does this by shallow + * cloning the node, restoring the attributes and then adding the parsed children. * * @param string $in_fragment xml fragment which will be merged into tree * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function replaceChildren($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } - if (XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { + + if (XML_XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); return $importedNodes; } - // nix all the children - $oldPointer = $this->pointer; - if (!is_array($attributeNodes = $this->pointer->attributes())) { - $attributeNodes = array(); - } - $this->pointer = $this->xml->create_element($this->nodeName()); - foreach ($attributeNodes as $attributeNode) { - $this->setAttribute($attributeNode->name, $attributeNode->value); + + // nix all the children by overwriting node and fixing attributes + $attributes = $this->pointer->has_attributes() ? $this->pointer->attributes() : array(); + $this->pointer->replace_node($clone = $this->pointer->clone_node()); + $this->pointer = $clone; + + foreach($attributes as $attributeNode) { + // waiting on set_attribute_node() to work here + $this->pointer->set_attribute($attributeNode->node_name(), $attributeNode->value()); } + foreach ($importedNodes as $importedNode) { - $this->pointer->add_child($importedNode); + $this->pointer->append_child($importedNode); } - /** should just be able to replace_node here, but doesn't work like it should **/ - $this->pointer = $this->xml->insert_before($this->pointer, $oldPointer); - - $oldPointer->unlink(); $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); } @@ -939,13 +1018,13 @@ * @access public * @return string xml string, a concatenation of all the children of the element node */ - function dumpChildren($in_xpathQuery = null, $in_movePointer = false) + function dumpChildren($in_xpathQuery = null, $in_movePointer = false, $in_format = true) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } - $xmlString = trim($this->xml->dump_node($this->pointer)); + $xmlString = trim($this->xml->dump_node($this->pointer, $in_format)); $xmlString = substr($xmlString,strpos($xmlString,'>')+1,-(strlen($this->nodeName())+3)); $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); @@ -963,20 +1042,20 @@ * @param int $in_compression (optional) ratio of compression using zlib (0-9) * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function toFile($in_file, $in_compression = 0) { // If the file does not exist, make sure we can write in this directory if (!file_exists($in_file)) { if (!is_writable(dirname($in_file))) { - return PEAR::raiseError(null, XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XML_XPath_Error', true); } } // If the file exists, make sure we can overwrite it else { if (!is_writable($in_file)) { - return PEAR::raiseError(null, XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XML_XPath_Error', true); } } @@ -1000,22 +1079,23 @@ * @access public * @return string xml string, starting at pointer */ - function toString($in_xpathQuery = null, $in_movePointer = false, $in_format = false) + function toString($in_xpathQuery = null, $in_movePointer = false, $in_format = true) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } if ($this->nodeType() == XML_DOCUMENT_NODE) { - $xmlString = $this->xml->dump_mem(); + $xmlString = $this->xml->dump_mem($in_format); } else { - $xmlString = $this->xml->dump_node($this->pointer); + $xmlString = $this->xml->dump_node($this->pointer, $in_format); } + /* if ($in_format) { $xmlString = escapeshellarg($xmlString); $xmlString = `echo $xmlString | {$this->xmllint} --format - 2>&1`; - } + }*/ $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); @@ -1045,16 +1125,16 @@ * @param object $in_node node to move to in the xml document * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function setPointer($in_node) { // if this is an error object, just return it - if (XPath::isError($in_node)) { + if (XML_XPath::isError($in_node)) { return $in_node; } elseif (!$this->_is_dom_node($in_node)) { - return PEAR::raiseError(null, XPATH_NODE_REQUIRED, null, E_USER_WARNING, $in_node, 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_NODE_REQUIRED, null, E_USER_WARNING, $in_node, 'XML_XPath_Error', true); } else { // we are okay, set the node and return true @@ -1082,12 +1162,12 @@ $fakeChildren = array($in_xmlData); } else { - $fake = @xmldoc('<fake>'.$in_xmlData.'</fake>'); + $fake = @domxml_open_mem('<fake>'.$in_xmlData.'</fake>'); if (!$fake) { - return PEAR::raiseError(null, XML_PARSE_ERROR, null, E_USER_WARNING, $in_xmlData, 'XPath_Error', true); + return PEAR::raiseError(null, XML_PARSE_ERROR, null, E_USER_WARNING, $in_xmlData, 'XML_XPath_Error', true); } - $fakeRoot = $fake->root(); - $fakeChildren = $fakeRoot->children(); + $fakeRoot = $fake->document_element(); + $fakeChildren = $fakeRoot->has_child_nodes() ? $fakeRoot->child_nodes() : array(); } return $fakeChildren; } @@ -1104,11 +1184,11 @@ * @param int $in_count length of manipulation * * @access private - * @return object XPath_Error on fail + * @return object XML_XPath_Error on fail */ function _set_content($in_content, $in_xpathQuery, $in_movePointer, $in_replace, $in_offset = 0, $in_count = 0) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE, XML_PI_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE, XML_PI_NODE)))) { return $result; } @@ -1116,10 +1196,10 @@ // little hack to get appendData to use this function here...special little exception $in_offset = is_null($in_offset) ? strlen($data) : $in_offset; if (!is_int($in_offset) || $in_offset < 0 || $in_offset > strlen($data)) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XPath_Error', true); + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XML_XPath_Error', true); } elseif (!is_int($in_count) || $in_count < 0) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XPath_Error', true); + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XML_XPath_Error', true); } else { if ($in_replace) { @@ -1149,7 +1229,7 @@ */ function _is_dom_node($in_object) { - return (is_object($in_object) && is_class_type($in_object, 'domnode')); + return (is_object($in_object) && is_a_php_class($in_object, 'domnode')); } // }}} @@ -1163,7 +1243,7 @@ */ function _restore_bookmark() { - $this->setPointer($this->bookmark); + $this->pointer = $this->bookmark; } // }}} @@ -1177,8 +1257,8 @@ */ function _set_bookmark($in_location) { - $this->bookmark = $this->getPointer(); - $this->setPointer($in_location); + $this->bookmark = $this->pointer; + $this->pointer = $in_location; } // }}} @@ -1187,7 +1267,7 @@ /** * The function will allow an on the quick xpath query to move the internal pointer before * invoking the xmldom function. The requirements are that the xpath query must return - * an XPATH_NODESET and have at least one node. If not, an XPath_Error will be returned + * an XPATH_NODESET and have at least one node. If not, an XML_XPath_Error will be returned * ** In addition this function does a check on the correct nodeType to run the caller method * * @param string $in_xpathQuery optional xpath query to move the internal pointer @@ -1195,7 +1275,7 @@ * @param array $in_nodeTypes required nodeType list for the caller method * * @access private - * @return boolean true on success, XPath_Error on error + * @return boolean true on success, XML_XPath_Error on error */ function _quick_evaluate_init($in_xpathQuery = null, $in_movePointer = false, $in_nodeTypes = null) { @@ -1204,19 +1284,19 @@ $tmpPointer = $in_xpathQuery; } else { - if (XPath::isError($resultObj = $this->evaluate($in_xpathQuery))) { + if (XML_XPath::isError($resultObj = $this->evaluate($in_xpathQuery))) { return $resultObj; } // make sure we have at least one node if (!($resultObj->numResults() && $resultObj->resultType() == XPATH_NODESET)) { - return PEAR::raiseError(null, XPATH_INVALID_NODESET, null, E_USER_WARNING, "XPath query: $in_xpathQuery", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODESET, null, E_USER_WARNING, "XML_XPath query: $in_xpathQuery", 'XML_XPath_Error', true); } $resultObj->nextNode(); $tmpPointer = $resultObj->getPointer(); } // if we are moving the internal pointer, then do it now if ($in_movePointer) { - $this->setPointer($tmpPointer); + $this->pointer = $tmpPointer; } // set the bookmark if we only want to temporarily move the pointer else { @@ -1224,9 +1304,9 @@ } } // see if we have a restricted nodeType requirement - if (is_array($in_nodeTypes) && !in_array($this->nodeType(), $in_nodeTypes)) { + if (is_array($in_nodeTypes) && !in_array($nodeType = $this->pointer->node_type(), $in_nodeTypes)) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return PEAR::raiseError(null, XPATH_INVALID_NODETYPE, null, E_USER_WARNING, "Required type: ".implode(" or ", $in_nodeTypes).", Provided type: ".$this->nodeType(), 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODETYPE, null, E_USER_WARNING, "Required type: ".implode(" or ", $in_nodeTypes).", Provided type: ".$nodeType, 'XML_XPath_Error', true); } else { return true; Index: pear/XML_XPath/XPath/error.php diff -u pear/XML_XPath/XPath/error.php:1.2 pear/XML_XPath/XPath/error.php:1.3 --- pear/XML_XPath/XPath/error.php:1.2 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath/error.php Fri May 24 01:05:16 2002 @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: error.php,v 1.2 2002/03/16 09:14:27 dallen Exp $ +// $Id: error.php,v 1.3 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -26,44 +26,49 @@ // }}} -// {{{ class XPath_Error +// {{{ class XML_XPath_Error /** - * Error class for the XPath interface, which just prepares some variables and spawns PEAR_Error + * Error class for the XML_XPath interface, which just prepares some variables and spawns PEAR_Error * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath_Error extends PEAR_Error { +class XML_XPath_Error extends PEAR_Error { // {{{ properties - /** @var string prefix of all error messages */ - var $error_message_prefix = 'XPath Error: '; + /** + * Message in front of the error message + * @var string $error_message_prefix + */ + var $error_message_prefix = 'XML_XPath Error: '; // }}} // {{{ constructor /** - * Creates an xpath error object, extending the PEAR_Error class - * - * @param int $code the xpath error code - * @param int $mode the reaction to the error, either return, die or trigger/callback - * @param int $level intensity of the error (PHP error code) - * @param mixed $debuginfo any information that can inform user as to nature of the error - */ - function XPath_Error($code = XPATH_ERROR, $mode = PEAR_ERROR_RETURN, + * Creates an XML_XPath error object, extending the PEAR_Error class + * + * @param int $code the xpath error code + * @param int $mode the reaction to the error, either return, die or trigger/callback + * @param int $level intensity of the error (PHP error code) + * @param mixed $debuginfo any information that can inform user as to nature of the error + * + * @access private + */ + function XML_XPath_Error($code = XML_XPATH_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null) { if (is_int($code)) { - $this->PEAR_Error(XPath::errorMessage($code), $code, $mode, $level, $debuginfo); + $this->PEAR_Error(XML_XPath::errorMessage($code), $code, $mode, $level, $debuginfo); } else { - $this->PEAR_Error("Invalid error code: $code", XPATH_ERROR, $mode, $level, $debuginfo); + $this->PEAR_Error("Invalid error code: $code", XML_XPATH_ERROR, $mode, $level, $debuginfo); } } Index: pear/XML_XPath/XPath/result.php diff -u pear/XML_XPath/XPath/result.php:1.6 pear/XML_XPath/XPath/result.php:1.7 --- pear/XML_XPath/XPath/result.php:1.6 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath/result.php Fri May 24 01:05:16 2002 @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: result.php,v 1.6 2002/03/16 09:14:27 dallen Exp $ +// $Id: result.php,v 1.7 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -27,30 +27,30 @@ // }}} // {{{ constants -define('XPATH_SORT_TEXT_ASCENDING', 1); -define('XPATH_SORT_NUMBER_ASCENDING', 2); -define('XPATH_SORT_NATURAL_ASCENDING', 3); -define('XPATH_SORT_TEXT_DESCENDING', 4); -define('XPATH_SORT_NUMBER_DESCENDING', 5); -define('XPATH_SORT_NATURAL_DESCENDING', 6); +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 XPath_result +// {{{ class XML_XPath_result /** - * Interface for an XPath result so that one can cycle through the result set and manipulate + * 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. * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath_result extends XPath_common { +class XML_XPath_result extends XML_XPath_common { // {{{ properties /** @var object reference to result object */ @@ -77,12 +77,12 @@ // }}} // {{{ constructor - function XPath_result($in_result, $in_query, &$in_xml, &$in_ctx) + function XML_XPath_result($in_result, $in_query, &$in_xml, &$in_ctx) { $this->result = &$in_result; $this->query = $in_query; $this->type = $this->result->type; - $this->data = $this->result->nodeset ? $this->result->nodeset : $this->result->value; + $this->data = isset($this->result->nodeset) ? $this->result->nodeset : $this->result->value; $this->index = 0; $this->xml = &$in_xml; $this->ctx = &$in_ctx; @@ -195,12 +195,12 @@ * @param mixed $in_index either an integer index or the string 'first' or 'last' * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function setNodeIndex($in_index) { if (!$this->type == XPATH_NODESET) { - return PEAR::raiseError(null, XPATH_INVALID_NODESET, null, E_USER_NOTICE, "Cannot assign index $in_index to non-nodeset result in query {$this->query}", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODESET, null, E_USER_NOTICE, "Cannot assign index $in_index to non-nodeset result in query {$this->query}", 'XML_XPath_Error', true); } if ($in_index == 'last') { $this->index = sizeOf($this->data); @@ -210,13 +210,13 @@ } elseif (is_int($in_index)) { if ($in_index > sizeOf($this->data)) { - return PEAR::raiseError(null, XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Invalid index $in_index in query {$this->query}", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Invalid index $in_index in query {$this->query}", 'XML_XPath_Error', true); } elseif ($in_index > 0) { $this->index = $in_index; } else { - return PEAR::raiseError(null, XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Negative index $in_index is invalid", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Negative index $in_index is invalid", 'XML_XPath_Error', true); } } $this->pointer = $this->data[$this->index]; @@ -235,24 +235,24 @@ * ascending order. * * @param string $in_sortXpath relative xpath query location to each node in nodeset - * @param int $in_order either XPATH_SORT_TEXT_[DE|A]SCENDING, - * XPATH_SORT_NUMBER_[DE|A]SCENDING, - * XPATH_SORT_NATURAL_[DE|A]SCENDING + * @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 * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ - function sort($in_sortXpath = '.', $in_order = XPATH_SORT_TEXT_ASCENDING) + function sort($in_sortXpath = '.', $in_order = XML_XPATH_SORT_TEXT_ASCENDING) { if ($this->resultType() != XPATH_NODESET) { - return PEAR::raiseError(null, XPATH_INVALID_NODESET, null, E_USER_NOTICE, $this->data, 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODESET, null, E_USER_NOTICE, $this->data, 'XPath_Error', true); } if ($in_sortXpath == '') { $in_sortXpath = '.'; } $xpathResult = @$this->ctx->xpath_eval($this->query . '/' . $in_sortXpath . '|' . $this->query); if (!$xpathResult || !$xpathResult->nodeset) { - return PEAR::raiseError(null, XPATH_INVALID_QUERY, null, E_USER_NOTICE, "Query {$this->query}/$in_sortXPath", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_QUERY, null, E_USER_NOTICE, "Query {$this->query}/$in_sortXPath", 'XML_XPath_Error', true); } $data = array(); $this->index = 0; @@ -263,41 +263,52 @@ } else { foreach ($xpathResult->nodeset as $index => $node) { - if ($node != $this->data[$this->index]) { + if (!isset($this->data[$this->index]) || $node != $this->data[$this->index]) { continue; } - if ($xpathResult->nodeset[$index + 1] == $this->data[$this->index]) { - array_push($data, ''); - } - elseif(isset($xpathResult->nodeset[$index + 1])) { - array_push($data, $xpathResult->nodeset[$index + 1]->get_content()); + + if (isset($xpathResult->nodeset[$index + 1])) { + if ($xpathResult->nodeset[$index + 1] == $this->data[$this->index]) { + array_push($data, ''); + } + else { + array_push($data, $xpathResult->nodeset[$index + 1]->get_content()); + } } + $this->index++; } } + switch ($in_order) { - case XPATH_SORT_TEXT_ASCENDING: + case XML_XPATH_SORT_TEXT_ASCENDING: asort($data, SORT_STRING); - break; - case XPATH_SORT_NUMBER_ASCENDING: + break; + + case XML_XPATH_SORT_NUMBER_ASCENDING: asort($data, SORT_NUMERIC); - break; - case XPATH_SORT_NATURAL_ASCENDING: + break; + + case XML_XPATH_SORT_NATURAL_ASCENDING: natsort($data); - break; - case XPATH_SORT_TEXT_DESCENDING: + break; + + case XML_XPATH_SORT_TEXT_DESCENDING: arsort($data, SORT_STRING); - break; - case XPATH_SORT_NUMBER_DESCENDING: + break; + + case XML_XPATH_SORT_NUMBER_DESCENDING: arsort($data, SORT_NUMERIC); - break; - case XPATH_SORT_NATURAL_DESCENDING: + break; + + case XML_XPATH_SORT_NATURAL_DESCENDING: natsort($data); $data = array_reverse($data, TRUE); - break; + break; + default: asort($data); - break; + break; } $dataReordered = array(); $this->index = 0;
Index: pear/XML_XPath/TODO diff -u pear/XML_XPath/TODO:1.1 pear/XML_XPath/TODO:1.2 --- pear/XML_XPath/TODO:1.1 Fri Mar 15 03:38:34 2002 +++ pear/XML_XPath/TODO Fri May 24 01:05:16 2002 @@ -9,14 +9,18 @@ Status Description =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - [*] A more formal and informative interface to the load() function + [@] implement siblingNode and childNode to get a tag by name + [@] sort for results + + [@] A more formal and informative interface to the load() function, used 'file/string/object' + + [@] prevent duplicate root in appendChild() + [*] make an example.php and example.out for people to read through [*] make a short test harness just so I know I don't commit bad shit - [@] prevent duplicate root in appendChild() - [*] finally figured out substitute entities default, so see if we can make this usable in the class @@ -24,5 +28,3 @@ now [*] considering doing substringData for attribute nodes...just seems to make sense - - [@] sort for results Index: pear/XML_XPath/XPath.php diff -u pear/XML_XPath/XPath.php:1.7 pear/XML_XPath/XPath.php:1.8 --- pear/XML_XPath/XPath.php:1.7 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath.php Fri May 24 01:05:16 2002 @@ -4,7 +4,7 @@ // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ -// | Copyright (c) 1997-2001 The PHP Group | +// | Copyright (c) 1997-2002 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 | @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: XPath.php,v 1.7 2002/03/16 09:14:27 dallen Exp $ +// $Id: XPath.php,v 1.8 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -28,52 +28,52 @@ // {{{ error codes /* - * Error codes for the XPath interface, which will be mapped to textual messages - * in the XPath::errorMessage() function. If you are to add a new error code, be - * sure to add the textual messages to the XPath::errorMessage() function as well + * Error codes for the XML_XPath interface, which will be mapped to textual messages + * in the XML_XPath::errorMessage() function. If you are to add a new error code, be + * sure to add the textual messages to the XML_XPath::errorMessage() function as well */ -define("XPATH_OK", 1); -define("XPATH_ERROR", -1); -define("XPATH_ALREADY_EXISTS", -2); -define("XPATH_INVALID_DOCUMENT", -3); -define("XPATH_INVALID_QUERY", -4); -define("XPATH_NO_DOM", -5); -define("XPATH_INVALID_INDEX", -6); -define("XPATH_INVALID_NODESET", -7); -define("XPATH_NOT_LOADED", -8); -define("XPATH_INVALID_NODETYPE", -9); -define("XPATH_FILE_NOT_WRITABLE", -10); -define("XPATH_NODE_REQUIRED", -11); -define("XPATH_INDEX_SIZE", -12); -define("XML_PARSE_ERROR", -13); -define("XML_DUPLICATE_ROOT", -14); +define('XML_XPATH_OK', 1); +define('XML_XPATH_ERROR', -1); +define('XML_XPATH_ALREADY_EXISTS', -2); +define('XML_XPATH_INVALID_DOCUMENT', -3); +define('XML_XPATH_INVALID_QUERY', -4); +define('XML_XPATH_NO_DOM', -5); +define('XML_XPATH_INVALID_INDEX', -6); +define('XML_XPATH_INVALID_NODESET', -7); +define('XML_XPATH_NOT_LOADED', -8); +define('XML_XPATH_INVALID_NODETYPE', -9); +define('XML_XPATH_FILE_NOT_WRITABLE', -10); +define('XML_XPATH_NODE_REQUIRED', -11); +define('XML_XPATH_INDEX_SIZE', -12); +define('XML_PARSE_ERROR', -13); +define('XML_DUPLICATE_ROOT', -14); // }}} // {{{ includes -require_once "PEAR.php"; -require_once "XPath/common.php"; -require_once "XPath/result.php"; -require_once "XPath/error.php"; +require_once 'PEAR.php'; +require_once 'XPath/common.php'; +require_once 'XPath/result.php'; +require_once 'XPath/error.php'; // }}} -// {{{ class XPath +// {{{ class XML_XPath /** - * The main "XPath" class is simply a container class with some methods for + * The main "XML_XPath" class is simply a container class with some methods for * creating DOM xml objects and preparing error codes * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath extends XPath_common { +class XML_XPath extends XML_XPath_common { // {{{ properties /** @var object xml data object */ @@ -91,12 +91,12 @@ // }}} // {{{ constructor - function Xpath($in_xml = null) + function XML_Xpath($in_xml = null, $in_type = 'string') { // load the xml document if passed in here // if not defined, require load() to be called if (!is_null($in_xml)) { - if(XPath::isError($result = $this->load($in_xml))) { + if (XML_XPath::isError($result = $this->load($in_xml, $in_type))) { $this = $result; } } @@ -114,40 +114,40 @@ * @param mixed $in_xml xml document, in one of 3 forms (object, string or file) * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ - function load($in_xml) + function load($in_xml, $in_type = 'string') { // if we already have a document loaded, then throw a warning if ($this->loaded) { - return PEAR::raiseError(null, XPATH_ALREADY_EXISTS, null, E_USER_WARNING, $this->xml->root(), 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_ALREADY_EXISTS, null, E_USER_WARNING, $this->xml->root(), 'XML_XPath_Error', true); } // in this case, we already have an xmldom object - if (is_class_type($in_xml, 'domdocument')) { + if ($in_type == 'object' && get_class($in_xml) == 'DomDocument') { $this->xml = $in_xml; } // we can read the file, so use xmldocfile to make a xmldom object - elseif(file_exists($in_xml) && is_readable($in_xml)) { - $this->xml = @xmldocfile($in_xml); + elseif ($in_type == 'file' && @file_exists($in_xml)) { + $this->xml = @domxml_open_file($in_xml); } // this is a string, so attempt to make an xmldom object from string - elseif(is_string($in_xml)) { - $this->xml = @xmldoc($in_xml); + elseif($in_type == 'string' && is_string($in_xml)) { + $this->xml = @domxml_open_mem($in_xml); } // not a valid xml instance, so throw error else { - return PEAR::raiseError(null, XPATH_INVALID_DOCUMENT, null, E_USER_ERROR, "The xml data '$in_xml' could not be parsed to xml dom", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_DOCUMENT, null, E_USER_ERROR, "The xml data '$in_xml' could not be parsed to xml dom", 'XML_XPath_Error', true); } - // make sure a xmldom object was created, and if so initialized the state - if (is_class_type($this->xml, 'domdocument')) { + // make sure a domxml object was created, and if so initialized the state + if (get_class($this->xml) == 'DomDocument') { $this->loaded = true; $this->ctx = $this->xml->xpath_new_context(); $this->pointer = $this->xml->root(); return true; } - // we could not make a xmldom object, so throw an error + // we could not make a domxml object, so throw an error else { - return PEAR::raiseError(null, XPATH_NO_DOM, null, E_USER_ERROR, "A DomDocument could not be instantiated from '$in_xml'", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_NO_DOM, null, E_USER_ERROR, "A DomDocument could not be instantiated from '$in_xml'", 'XML_XPath_Error', true); } } @@ -162,12 +162,12 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return mixed number of nodes or value of scalar result {or XPath_Error exception} + * @return mixed number of nodes or value of scalar result {or XML_XPath_Error exception} */ function getOne($in_xpathQuery, $in_movePointer = false) { // Execute the xpath query and return the results, then reset the result index - if (XPath::isError($result = $this->evaluate($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->evaluate($in_xpathQuery, $in_movePointer))) { return $result; } return $result->getData(); @@ -177,25 +177,25 @@ // {{{ void evaluate() /** - * Evaluate the xpath expression on the loaded xml document. An XPath_Result object is + * Evaluate the xpath expression on the loaded xml document. An XML_XPath_Result object is * returned which can be used to manipulate the results * * @param string $in_xpathQuery xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return object result object {or XML_XPath_Error exception} */ function evaluate($in_xpathQuery, $in_movePointer = false) { // Make sure we have loaded an xml document and were able to create an xpath context - if (!is_class_type($this->ctx, 'xpathcontext')) { - return PEAR::raiseError(null, XPATH_NOT_LOADED, null, E_USER_ERROR, null, 'XPath_Error', true); + if (!is_a_php_class($this->ctx, 'xpathcontext')) { + return PEAR::raiseError(null, XML_XPATH_NOT_LOADED, null, E_USER_ERROR, null, 'XML_XPath_Error', true); } if (!$result = @xpath_eval($this->ctx, $in_xpathQuery)) { - return PEAR::raiseError(null, XPATH_INVALID_QUERY, null, E_USER_WARNING, "XPath query: $in_xpathQuery", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_QUERY, null, E_USER_WARNING, "XML_XPath query: $in_xpathQuery", 'XML_XPath_Error', true); } - $resultObj = new XPath_result($result, $in_xpathQuery, $this->xml, $this->ctx); + $resultObj = new XML_XPath_result($result, $in_xpathQuery, $this->xml, $this->ctx); if ($in_movePointer && $resultObj->resultType() == XPATH_NODESET && $resultObj->numResults()) { $this->setPointer($resultObj->getPointer()); @@ -207,7 +207,7 @@ // {{{ boolean isError() /** - * Tell whether a result code from a XPath method is an error. + * Tell whether a result code from a XML_XPath method is an error. * * @param object $in_value object in question * @@ -216,14 +216,14 @@ */ function isError($in_value) { - return is_class_type($in_value, 'xpath_error'); + return is_a($in_value, 'xml_xpath_error'); } // }}} // {{{ mixed errorMessage() /** - * Return a textual error message for an XPath error code. + * Return a textual error message for an XML_XPath error code. * * @param int $in_value error code * @@ -238,31 +238,31 @@ // define the varies error messages if (!isset($errorMessages)) { $errorMessages = array( - XPATH_OK => 'no error', - XPATH_ERROR => 'unknown error', - XPATH_ALREADY_EXISTS => 'xml document already loaded', - XPATH_INVALID_DOCUMENT => 'invalid xml document', - XPATH_INVALID_QUERY => 'invalid xpath query', - XPATH_NO_DOM => 'DomDocument could not be instantiated', - XPATH_INVALID_INDEX => 'invalid index', - XPATH_INVALID_NODESET => 'requires nodeset and one of appropriate type', - XPATH_NOT_LOADED => 'DomDocument has not been loaded', - XPATH_INVALID_NODETYPE => 'invalid nodetype for requested feature', - XPATH_FILE_NOT_WRITABLE => 'file could not be written', - XPATH_NODE_REQUIRED => 'DomNode required for operation', - XPATH_INDEX_SIZE => 'index given out of range', + XML_XPATH_OK => 'no error', + XML_XPATH_ERROR => 'unknown error', + XML_XPATH_ALREADY_EXISTS => 'xml document already loaded', + XML_XPATH_INVALID_DOCUMENT => 'invalid xml document', + XML_XPATH_INVALID_QUERY => 'invalid xpath query', + XML_XPATH_NO_DOM => 'DomDocument could not be instantiated', + XML_XPATH_INVALID_INDEX => 'invalid index', + XML_XPATH_INVALID_NODESET => 'requires nodeset and one of appropriate type', + XML_XPATH_NOT_LOADED => 'DomDocument has not been loaded', + XML_XPATH_INVALID_NODETYPE => 'invalid nodetype for requested feature', + XML_XPATH_FILE_NOT_WRITABLE => 'file could not be written', + XML_XPATH_NODE_REQUIRED => 'DomNode required for operation', + XML_XPATH_INDEX_SIZE => 'index given out of range', XML_PARSE_ERROR => 'parse error in xml string', XML_DUPLICATE_ROOT => 'root element already exists' ); } // If this is an error object, then grab the corresponding error code - if (XPath::isError($in_value)) { + if (XML_XPath::isError($in_value)) { $in_value = $in_value->getCode(); } // return the textual error message corresponding to the code - return isset($errorMessages[$in_value]) ? $errorMessages[$in_value] : $errorMessages[XPATH_ERROR]; + return isset($errorMessages[$in_value]) ? $errorMessages[$in_value] : $errorMessages[XML_XPATH_ERROR]; } // }}} Index: pear/XML_XPath/package.xml diff -u pear/XML_XPath/package.xml:1.3 pear/XML_XPath/package.xml:1.4 --- pear/XML_XPath/package.xml:1.3 Mon Apr 1 07:13:59 2002 +++ pear/XML_XPath/package.xml Fri May 24 01:05:16 2002 @@ -23,13 +23,13 @@ </maintainer> </maintainers> <deps> - <dep type="php" rel="ge" version="4.2.0" /> + <dep type="php" rel="ge" version="4.2.1" /> </deps> <release> <license>PHP 2.01</license> <state>beta</state> - <version>1.1</version> - <date>2002-03-10</date> + <version>1.0</version> + <date>2002-05-23</date> <notes> This is the initial independent PEAR release. </notes> Index: pear/XML_XPath/XPath/common.php diff -u pear/XML_XPath/XPath/common.php:1.11 pear/XML_XPath/XPath/common.php:1.12 --- pear/XML_XPath/XPath/common.php:1.11 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath/common.php Fri May 24 01:05:16 2002 @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: common.php,v 1.11 2002/03/16 09:14:27 dallen Exp $ +// $Id: common.php,v 1.12 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -28,7 +28,9 @@ // {{{ functions /** - * is_a is only defined in php CVS, so I implemented its functionality for the time being + * is_a is only defined in php for user functions, + * so I implemented its functionality for php objects + * until they fix (or never fix) this problem * * @param object $class the class to check * @param string $match class name you are looking for @@ -36,24 +38,33 @@ * @access public * @return boolean whether the class is of the class type or a descendent of the class */ -function is_class_type($class, $match) +function is_a_php_class($class, $match) { if (empty($class)) { return false; } + $class = is_object($class) ? get_class($class) : $class; if (strtolower($class) == strtolower($match)) { return true; } - return is_class_type(get_parent_class($class), $match); + + return is_a_php_class(get_parent_class($class), $match); } // }}} - -// {{{ class XPath_common +/** + * changes to domxml that I have to look at + * + * implement the striping of formating on the way in possibly + * append_sibling() added + * insert_before() now copies node before inserting + * domxml_parser() might be good for bringing in stuff + */ +// {{{ class XML_XPath_common /** - * The XPath_common class contains the DOM functions used to manipulate + * The XML_XPath_common class contains the DOM functions used to manipulate * and maneuver through the xml tree. The main thing to understand is * that all operations work around a single pointer. This pointer is your * place holder within the document. Each function you run assumes the @@ -64,33 +75,35 @@ * prepares the pointer to the requested location in the tree if an xpath query * or pointer object is provided. In addition, the init() function checks to * see that the node type is acceptable for the method, and if not throws an - * XPath_Error exception. + * XML_XPath_Error exception. If you want to execute a function and then remain + * in the location of your query, then you specify that you want to move the pointer. + * For the DOM step functions, this is the default action. * * Note: All offsets in the CharacterData interface start from 0. * - * The object model of XPath is as follows (indentation means inheritance): + * The object model of XML_XPath is as follows (indentation means inheritance): * - * XPath_common The main functionality of the XPath class is here. This + * XML_XPath_common The main functionality of the XML_XPath class is here. This * | holds all the DOM functions for manipulating and maneuvering * | through the DOM tree. * | - * +-XPath The frontend for the XPath implementation. Provides default + * +-XML_XPath The frontend for the XML_XPath implementation. Provides default * | functions for preparing the main document, running xpath queries * | and handling errorMessages. * | - * +-Result Extended from the XPath_common class, this object is returned when + * +-Result Extended from the XML_XPath_common class, this object is returned when * an xpath query is executed and can be used to cycle through the * result nodeset or data * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath_common { +class XML_XPath_common { // {{{ properties /** @var object current location in xml document */ @@ -115,15 +128,20 @@ * @param boolean $in_movePointer (optional) move internal pointer with quick xpath query * * @access public - * @return string name of node corresponding to DOM recommendation {or XPath_Error exception} + * @return string name of node corresponding to DOM recommendation {or XML_XPath_Error exception} */ function nodeName($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (!is_null($in_xpathQuery) && XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } + $nodeName = $this->pointer->node_name(); - $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); + + if (!is_null($in_xpathQuery)) { + $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); + } + return $nodeName; } @@ -137,11 +155,11 @@ * @param boolean $in_movePointer (optional) move internal pointer with quick xpath query * * @access public - * @return int DOM type of the node {or XPath_Error exception} + * @return int DOM type of the node {or XML_XPath_Error exception} */ function nodeType($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } $nodeType = $this->pointer->node_type(); @@ -162,7 +180,7 @@ */ function parentNode($in_movePointer = true) { - $parent = $this->pointer->parent(); + $parent = $this->pointer->parent_node(); if ($parent) { if ($in_movePointer) { $this->pointer = $parent; @@ -178,6 +196,115 @@ } // }}} + // {{{ boolean siblingNode() + + /** + * Get the sibling based on the tag name of the sibling. An index can be + * specified which will get the nth sibling with that name. This function uses caching of + * the child array of the parent to speed up multiple uses of it, killing the cache when + * the internal pointer of the parent changes (this can be forced). This is not a DOM + * function, but convienent addition. + * + * @param string $in_name tagname of the sibling node + * @param int $in_index index of the sibling with this tagname (1 based) + * @param boolean $in_movePointer either move the internal pointer or return pointer + * @param boolean $in_clearCache force clear the cache of the siblings + * + * @access public + * @return boolean if the pointer could be moved, or pointer if $in_movePointer is false + */ + function siblingNode($in_name, $in_index = 1, $in_movePointer = true, $in_clearCache = false) + { + static $nameList, $previousParent; + settype($in_index, 'int'); + $index = $in_index > 0 ? $in_index - 1 : 0; + // if we have changed locations, then reset the child array + $parent = $this->pointer->parent_node(); + if ($parent != $previousParent || $in_clearCache) { + $previousParent = $parent; + $nameList = array(); + } + // if the child array is not set, make it now + // (can be dangerous if DOM changes have occured) + if (empty($nameList)) { + $childNodes = $parent->child_nodes(); + settype($children, 'array'); + foreach ($childNodes as $childNode) { + if ($childNode->is_blank_node() && $this->skipBlanks) { + continue; + } + $nameList[$childNode->node_name()][] = $childNode; + } + } + // either move the pointer or return it + if (isset($nameList[$in_name][$index])) { + if ($in_movePointer) { + $this->pointer = $nameList[$in_name][$index]; + return true; + } + else { + return $nameList[$in_name][$index]; + } + } + else { + return false; + } + } + + // }}} + // {{{ boolean childNode() + + /** + * Get the direct descendant child based on the tag name of the child. An index can be + * specified which will get the nth child with that name. This function uses caching of + * the child array to speed up multiple uses of it, killing the cache when the internal + * pointer changes (this can be forced). This is not a DOM function, but convienent one. + * + * @param string $in_name tagname of the child node + * @param int $in_index index of the sibling with this tagname (1 based) + * @param boolean $in_movePointer either move the internal pointer or return pointer + * @param boolean $in_clearCache force clear the cache of the children + * + * @access public + * @return boolean if the pointer could be moved, or pointer if $in_movePointer is false + */ + function childNode($in_name, $in_index = 1, $in_movePointer = true, $in_clearCache = false) + { + static $nameList, $previousPointer; + settype($in_index, 'int'); + $index = $in_index > 0 ? $in_index - 1 : 0; + // if we have changed locations, then reset the child array + if ($this->pointer != $previousPointer || $in_clearCache) { + $previousPointer = $this->pointer; + $nameList = array(); + } + // if the child array is not set, make it now (can be dangerous) + if (empty($nameList)) { + $childNodes = $this->pointer->child_nodes(); + settype($children, 'array'); + foreach ($childNodes as $childNode) { + if ($childNode->is_blank_node() && $this->skipBlanks) { + continue; + } + $nameList[$childNode->node_name()][] = $childNode; + } + } + // either move the pointer or return it + if (isset($nameList[$in_name][$index])) { + if ($in_movePointer) { + $this->pointer = $nameList[$in_name][$index]; + return true; + } + else { + return $nameList[$in_name][$index]; + } + } + else { + return false; + } + } + + // }}} // {{{ boolean nextSibling() /** @@ -364,59 +491,6 @@ } // }}} - // {{{ boolean getChildByTagName() - - /** - * Get the direct descendant child based on the tag name of the child. An index can be - * specified which will get the nth sibling with that name. This function uses caching of - * the child array to speed up multiple uses of it, killing the cache when the internal - * pointer changes (this can be forced). This is not a DOM function, but convienent one. - * - * @param string $in_name tagname of the child node - * @param int $in_index index of the sibling with this tagname (1 based) - * @param boolean $in_movePointer either move the internal pointer or return pointer - * @param boolean $in_clearCache force clear the cache of the children - * - * @access public - * @return boolean if the pointer could be moved, or pointer if $in_movePointer is false - */ - function getChildByTagName($in_name, $in_index = 1, $in_movePointer = true, $in_clearCache = false) - { - static $nameList, $previousPointer; - settype($in_index, 'int'); - $index = $in_index > 0 ? $in_index - 1 : 0; - // if we have changed locations, then reset the child array - if ($this->pointer != $previousPointer || $in_clearCache) { - $previousPointer = $this->pointer; - $nameList = array(); - } - // if the child array is not set, make it now (can be dangerous) - if (empty($nameList)) { - $childNodes = $this->pointer->children(); - settype($children, 'array'); - foreach ($childNodes as $childNode) { - if ($childNode->is_blank_node() && $this->skipBlanks) { - continue; - } - $nameList[$childNode->node_name()][] = $childNode; - } - } - // either move the pointer or return it - if (isset($nameList[$in_name][$index])) { - if ($in_movePointer) { - $this->pointer = $nameList[$in_name][$index]; - return true; - } - else { - return $nameList[$in_name][$index]; - } - } - else { - return false; - } - } - - // }}} // {{{ boolean isNodeType() /** @@ -427,11 +501,11 @@ * @param boolean $in_movePointer (optional) move internal pointer with quick xpath query * * @access public - * @return boolean same type of node {or XPath_Error exception} + * @return boolean same type of node {or XML_XPath_Error exception} */ function isNodeType($in_type, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } $isNodeType = $this->pointer->node_type() == $in_type ? true : false; @@ -449,11 +523,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return boolean has child nodes {or XPath_Error exception} + * @return boolean has child nodes {or XML_XPath_Error exception} */ function hasChildNodes($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } $hasChildNodes = $this->pointer->has_child_nodes() ? true : false; @@ -471,11 +545,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return boolean attributes exist {or XPath_Error exception} + * @return boolean attributes exist {or XML_XPath_Error exception} */ function hasAttributes($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $hasAttributes = $this->pointer->has_attributes() ? true : false; @@ -495,11 +569,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return boolean existence of attribute {or XPath_Error exception} + * @return boolean existence of attribute {or XML_XPath_Error exception} */ function hasAttribute($in_name, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $hasAttribute = false; @@ -527,11 +601,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return array associative array of attributes {or XPath_Error exception} + * @return array associative array of attributes {or XML_XPath_Error exception} */ function getAttributes($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $return = array(); @@ -550,20 +624,27 @@ /** * Retrieves an attribute value by name from the element node at the current pointer. * + * Grab the attribute value if it exists and return it. If the attribute does not + * exist, this function will return the boolean 'false', so be sure to check properly + * if the value is "" or if the attribute doesn't exist at all. + * * @param string $in_name Name of the attribute * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move the internal pointer with quick xpath query * * @access public - * @return string value of attribute {or XPath_Error exception} + * @return string value of attribute or false if attribute DNE {or XML_XPath_Error exception} */ function getAttribute($in_name, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } + $result = $this->pointer->get_attribute($in_name); + $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); + return $result; } @@ -581,11 +662,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function setAttribute($in_name, $in_value, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $this->pointer->set_attribute($in_name, $in_value); @@ -603,11 +684,11 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function removeAttribute($in_name, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } $this->pointer->remove_attribute($in_name); @@ -629,24 +710,24 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return string substring of the character data {or XPath_Error exception} + * @return string substring of the character data {or XML_XPath_Error exception} */ function substringData($in_offset = 0, $in_count = 0, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_ELEMENT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_ELEMENT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE)))) { return $result; } - if (!is_int($in_offset) || $in_offset < 0 || $in_offset > strlen($this->pointer->get_content())) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XPath_Error', true); + if (!is_int($in_count) || $in_count < 0) { + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XML_XPath_Error', true); } - elseif (!is_int($in_count) || $in_count < 0) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XPath_Error', true); + elseif (!is_int($in_offset) || $in_offset < 0 || $in_offset > strlen($content = $this->pointer->get_content())) { + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XML_XPath_Error', true); } + // if this is an element node, concat all the text children recursively else { - // if this is an element node, concat all the text children recursively - $return = $in_count ? substr($this->pointer->get_content(), $in_offset, $in_count) : - substr($this->pointer->get_content(), $in_offset); + $return = $in_count ? substr($content, $in_offset, $in_count) : + substr($content, $in_offset); } $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); return $return; @@ -664,7 +745,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function insertData($in_content, $in_offset = 0, $in_xpathQuery = null, $in_movePointer = false) { @@ -683,7 +764,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function deleteData($in_offset = 0, $in_count = 0, $in_xpathQuery = null, $in_movePointer = false) { @@ -703,7 +784,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function replaceData($in_content, $in_offset = 0, $in_count = 0, $in_xpathQuery = null, $in_movePointer = false) { @@ -721,7 +802,7 @@ * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function appendData($in_content, $in_xpathQuery = null, $in_movePointer = false) { @@ -729,7 +810,7 @@ } // }}} - // {{{ mixed replaceChild() + // {{{ object replaceChild() /** * Replaces the old child with the new child. If the new child is already in the document, @@ -737,41 +818,39 @@ * all of the nodes are inserted in the location of the old child. * * @param mixed $in_xmlData document fragment or node - * @param boolean $in_returnOriginal (optional) clone the old node and return reference to it * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return object pointer to old node (optional) {or XPath_Error exception} + * @return object pointer to old node {or XML_XPath_Error exception} + * @todo I should make it so an xml_xpath_result is returned or something */ - function replaceChild($in_xmlData, $in_returnOriginal = false, $in_xpathQuery = null, $in_movePointer = false) + function replaceChild($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_CDATA_SECTION_NODE, XML_PI_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_CDATA_SECTION_NODE, XML_PI_NODE)))) { return $result; } - if (XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { + if (XML_XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); return $importedNodes; } - $parent = $this->pointer->parent(); + + $parent = $this->pointer->parent_node(); + $lastNodeIndex = sizeOf($importedNodes) - 1; + // run through all the new nodes...on the last new node, run replace_child() foreach($importedNodes as $index => $importedNode) { - $node = $parent->insert_before($importedNode, $this->pointer); - if ($index == 0) { - $newNode = $node; + if ($index == $lastNodeIndex) { + $oldNode = $parent->replace_child($importedNode, $this->pointer); + } + else { + $parent->insert_before($importedNode, $this->pointer); } } - $oldNode = $this->pointer; - $this->pointer = $newNode; - - // to save memory we only return the original node if requested - $return = $in_returnOriginal ? $oldNode->clone_node(1) : null; - - $oldNode->unlink(); $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return $return; + return $oldNode; } // }}} @@ -786,24 +865,24 @@ * @param boolean $in_movePointer move internal pointer * * @access public - * @return object pointer to the first of the nodes appended {or XPath_Error exception} + * @return object pointer to the first of the nodes appended {or XML_XPath_Error exception} */ function appendChild($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_DOCUMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_DOCUMENT_NODE)))) { return $result; } // if this is a document node, make sure no root exists - if ($this->isNodeType(XML_DOCUMENT_NODE) && $this->xml->root()) { + if ($this->isNodeType(XML_DOCUMENT_NODE) && $this->xml->document_element()) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return PEAR::raiseError(null, XML_DUPLICATE_ROOT, null, E_USER_WARNING, null, 'XPath_Error', true); + return PEAR::raiseError(null, XML_DUPLICATE_ROOT, null, E_USER_WARNING, null, 'XML_XPath_Error', true); } - if (XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { + if (XML_XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { return $importedNodes; } foreach($importedNodes as $index => $importedNode) { - $node = $this->pointer->add_child($importedNode); + $node = $this->pointer->append_child($importedNode); if ($index == 0) { $newNode = $node; } @@ -827,17 +906,17 @@ */ function insertBefore($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } // we do some fance stuff here to make this general...make a fake node $importedNodes = $this->_build_fragment($in_xmlData); - if (XPath::isError($importedNodes)) { + if (XML_XPath::isError($importedNodes)) { return $importedNodes; } - $parent = $this->pointer->parent(); + $parent = $this->pointer->parent_node(); foreach($importedNodes as $index => $importedNode) { $node = $parent->insert_before($importedNode, $this->pointer); if ($index == 0) { @@ -854,33 +933,33 @@ // {{{ object removeChild() /** - * Removes the child node at the current pointer and returns it (optionally). + * Removes the child node at the current pointer and returns it. + * + * This function will remove a child from the list of children and will + * move the pointer to the parent node. * - * @param boolean $in_returnOriginal (optional) return the original node as a clone * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public * @return object cloned node of the removed node, ready to be put in another document - * ??? either put the pointer on the parent or previous sibling, then parent ??? */ - function removeChild($in_returnOriginal = false, $in_xpathQuery = null, $in_movePointer = false) + function removeChild($in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_PI_NODE, XML_CDATA_SECTION_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE, XML_TEXT_NODE, XML_COMMENT_NODE, XML_PI_NODE, XML_CDATA_SECTION_NODE)))) { return $result; } - // if we are returning the removedChild, clone it now - $return = $in_returnOriginal ? $this->pointer->clone_node(1) : null; - // set the node to be removed - $removeNode = $this->pointer; - // set the pointer to the parent (since this node is gone) - $this->pointer = $this->pointer->parent(); - $removeNode->unlink(); + // get the parent + $parent = $this->pointer->parent_node(); + // remove the child + $removedNode = $parent->remove_child($this->pointer); + // set pointer to the parent + $this->pointer = $parent; $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return $return; + return $removedNode; } // }}} @@ -889,40 +968,40 @@ /** * Not in the DOM specification, but certainly a convenient function. Allows you to pass * in an xml document fragment which will be parsed into an xml object and merged into the - * xml document, replacing all the previous children of the node. + * xml document, replacing all the previous children of the node. It does this by shallow + * cloning the node, restoring the attributes and then adding the parsed children. * * @param string $in_fragment xml fragment which will be merged into tree * @param string $in_xpathQuery (optional) quick xpath query * @param boolean $in_movePointer (optional) move internal pointer * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function replaceChildren($in_xmlData, $in_xpathQuery = null, $in_movePointer = false) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } - if (XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { + + if (XML_XPath::isError($importedNodes = $this->_build_fragment($in_xmlData))) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); return $importedNodes; } - // nix all the children - $oldPointer = $this->pointer; - if (!is_array($attributeNodes = $this->pointer->attributes())) { - $attributeNodes = array(); - } - $this->pointer = $this->xml->create_element($this->nodeName()); - foreach ($attributeNodes as $attributeNode) { - $this->setAttribute($attributeNode->name, $attributeNode->value); + + // nix all the children by overwriting node and fixing attributes + $attributes = $this->pointer->has_attributes() ? $this->pointer->attributes() : array(); + $this->pointer->replace_node($clone = $this->pointer->clone_node()); + $this->pointer = $clone; + + foreach($attributes as $attributeNode) { + // waiting on set_attribute_node() to work here + $this->pointer->set_attribute($attributeNode->node_name(), $attributeNode->value()); } + foreach ($importedNodes as $importedNode) { - $this->pointer->add_child($importedNode); + $this->pointer->append_child($importedNode); } - /** should just be able to replace_node here, but doesn't work like it should **/ - $this->pointer = $this->xml->insert_before($this->pointer, $oldPointer); - - $oldPointer->unlink(); $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); } @@ -939,13 +1018,13 @@ * @access public * @return string xml string, a concatenation of all the children of the element node */ - function dumpChildren($in_xpathQuery = null, $in_movePointer = false) + function dumpChildren($in_xpathQuery = null, $in_movePointer = false, $in_format = true) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_ELEMENT_NODE)))) { return $result; } - $xmlString = trim($this->xml->dump_node($this->pointer)); + $xmlString = trim($this->xml->dump_node($this->pointer, $in_format)); $xmlString = substr($xmlString,strpos($xmlString,'>')+1,-(strlen($this->nodeName())+3)); $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); @@ -963,20 +1042,20 @@ * @param int $in_compression (optional) ratio of compression using zlib (0-9) * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function toFile($in_file, $in_compression = 0) { // If the file does not exist, make sure we can write in this directory if (!file_exists($in_file)) { if (!is_writable(dirname($in_file))) { - return PEAR::raiseError(null, XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XML_XPath_Error', true); } } // If the file exists, make sure we can overwrite it else { if (!is_writable($in_file)) { - return PEAR::raiseError(null, XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_FILE_NOT_WRITABLE, null, E_USER_WARNING, "File: $in_file", 'XML_XPath_Error', true); } } @@ -1000,22 +1079,23 @@ * @access public * @return string xml string, starting at pointer */ - function toString($in_xpathQuery = null, $in_movePointer = false, $in_format = false) + function toString($in_xpathQuery = null, $in_movePointer = false, $in_format = true) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer))) { return $result; } if ($this->nodeType() == XML_DOCUMENT_NODE) { - $xmlString = $this->xml->dump_mem(); + $xmlString = $this->xml->dump_mem($in_format); } else { - $xmlString = $this->xml->dump_node($this->pointer); + $xmlString = $this->xml->dump_node($this->pointer, $in_format); } + /* if ($in_format) { $xmlString = escapeshellarg($xmlString); $xmlString = `echo $xmlString | {$this->xmllint} --format - 2>&1`; - } + }*/ $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); @@ -1045,16 +1125,16 @@ * @param object $in_node node to move to in the xml document * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function setPointer($in_node) { // if this is an error object, just return it - if (XPath::isError($in_node)) { + if (XML_XPath::isError($in_node)) { return $in_node; } elseif (!$this->_is_dom_node($in_node)) { - return PEAR::raiseError(null, XPATH_NODE_REQUIRED, null, E_USER_WARNING, $in_node, 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_NODE_REQUIRED, null, E_USER_WARNING, $in_node, 'XML_XPath_Error', true); } else { // we are okay, set the node and return true @@ -1082,12 +1162,12 @@ $fakeChildren = array($in_xmlData); } else { - $fake = @xmldoc('<fake>'.$in_xmlData.'</fake>'); + $fake = @domxml_open_mem('<fake>'.$in_xmlData.'</fake>'); if (!$fake) { - return PEAR::raiseError(null, XML_PARSE_ERROR, null, E_USER_WARNING, $in_xmlData, 'XPath_Error', true); + return PEAR::raiseError(null, XML_PARSE_ERROR, null, E_USER_WARNING, $in_xmlData, 'XML_XPath_Error', true); } - $fakeRoot = $fake->root(); - $fakeChildren = $fakeRoot->children(); + $fakeRoot = $fake->document_element(); + $fakeChildren = $fakeRoot->has_child_nodes() ? $fakeRoot->child_nodes() : array(); } return $fakeChildren; } @@ -1104,11 +1184,11 @@ * @param int $in_count length of manipulation * * @access private - * @return object XPath_Error on fail + * @return object XML_XPath_Error on fail */ function _set_content($in_content, $in_xpathQuery, $in_movePointer, $in_replace, $in_offset = 0, $in_count = 0) { - if (XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE, XML_PI_NODE)))) { + if (XML_XPath::isError($result = $this->_quick_evaluate_init($in_xpathQuery, $in_movePointer, array(XML_TEXT_NODE, XML_CDATA_SECTION_NODE, XML_COMMENT_NODE, XML_PI_NODE)))) { return $result; } @@ -1116,10 +1196,10 @@ // little hack to get appendData to use this function here...special little exception $in_offset = is_null($in_offset) ? strlen($data) : $in_offset; if (!is_int($in_offset) || $in_offset < 0 || $in_offset > strlen($data)) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XPath_Error', true); + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Offset: $in_offset", 'XML_XPath_Error', true); } elseif (!is_int($in_count) || $in_count < 0) { - $return = PEAR::raiseError(null, XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XPath_Error', true); + $return = PEAR::raiseError(null, XML_XPATH_INDEX_SIZE, null, E_USER_WARNING, "Count: $in_offset", 'XML_XPath_Error', true); } else { if ($in_replace) { @@ -1149,7 +1229,7 @@ */ function _is_dom_node($in_object) { - return (is_object($in_object) && is_class_type($in_object, 'domnode')); + return (is_object($in_object) && is_a_php_class($in_object, 'domnode')); } // }}} @@ -1163,7 +1243,7 @@ */ function _restore_bookmark() { - $this->setPointer($this->bookmark); + $this->pointer = $this->bookmark; } // }}} @@ -1177,8 +1257,8 @@ */ function _set_bookmark($in_location) { - $this->bookmark = $this->getPointer(); - $this->setPointer($in_location); + $this->bookmark = $this->pointer; + $this->pointer = $in_location; } // }}} @@ -1187,7 +1267,7 @@ /** * The function will allow an on the quick xpath query to move the internal pointer before * invoking the xmldom function. The requirements are that the xpath query must return - * an XPATH_NODESET and have at least one node. If not, an XPath_Error will be returned + * an XPATH_NODESET and have at least one node. If not, an XML_XPath_Error will be returned * ** In addition this function does a check on the correct nodeType to run the caller method * * @param string $in_xpathQuery optional xpath query to move the internal pointer @@ -1195,7 +1275,7 @@ * @param array $in_nodeTypes required nodeType list for the caller method * * @access private - * @return boolean true on success, XPath_Error on error + * @return boolean true on success, XML_XPath_Error on error */ function _quick_evaluate_init($in_xpathQuery = null, $in_movePointer = false, $in_nodeTypes = null) { @@ -1204,19 +1284,19 @@ $tmpPointer = $in_xpathQuery; } else { - if (XPath::isError($resultObj = $this->evaluate($in_xpathQuery))) { + if (XML_XPath::isError($resultObj = $this->evaluate($in_xpathQuery))) { return $resultObj; } // make sure we have at least one node if (!($resultObj->numResults() && $resultObj->resultType() == XPATH_NODESET)) { - return PEAR::raiseError(null, XPATH_INVALID_NODESET, null, E_USER_WARNING, "XPath query: $in_xpathQuery", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODESET, null, E_USER_WARNING, "XML_XPath query: $in_xpathQuery", 'XML_XPath_Error', true); } $resultObj->nextNode(); $tmpPointer = $resultObj->getPointer(); } // if we are moving the internal pointer, then do it now if ($in_movePointer) { - $this->setPointer($tmpPointer); + $this->pointer = $tmpPointer; } // set the bookmark if we only want to temporarily move the pointer else { @@ -1224,9 +1304,9 @@ } } // see if we have a restricted nodeType requirement - if (is_array($in_nodeTypes) && !in_array($this->nodeType(), $in_nodeTypes)) { + if (is_array($in_nodeTypes) && !in_array($nodeType = $this->pointer->node_type(), $in_nodeTypes)) { $this->_quick_evaluate_shutdown($in_xpathQuery, $in_movePointer); - return PEAR::raiseError(null, XPATH_INVALID_NODETYPE, null, E_USER_WARNING, "Required type: ".implode(" or ", $in_nodeTypes).", Provided type: ".$this->nodeType(), 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODETYPE, null, E_USER_WARNING, "Required type: ".implode(" or ", $in_nodeTypes).", Provided type: ".$nodeType, 'XML_XPath_Error', true); } else { return true; Index: pear/XML_XPath/XPath/error.php diff -u pear/XML_XPath/XPath/error.php:1.2 pear/XML_XPath/XPath/error.php:1.3 --- pear/XML_XPath/XPath/error.php:1.2 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath/error.php Fri May 24 01:05:16 2002 @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: error.php,v 1.2 2002/03/16 09:14:27 dallen Exp $ +// $Id: error.php,v 1.3 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -26,44 +26,49 @@ // }}} -// {{{ class XPath_Error +// {{{ class XML_XPath_Error /** - * Error class for the XPath interface, which just prepares some variables and spawns PEAR_Error + * Error class for the XML_XPath interface, which just prepares some variables and spawns PEAR_Error * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath_Error extends PEAR_Error { +class XML_XPath_Error extends PEAR_Error { // {{{ properties - /** @var string prefix of all error messages */ - var $error_message_prefix = 'XPath Error: '; + /** + * Message in front of the error message + * @var string $error_message_prefix + */ + var $error_message_prefix = 'XML_XPath Error: '; // }}} // {{{ constructor /** - * Creates an xpath error object, extending the PEAR_Error class - * - * @param int $code the xpath error code - * @param int $mode the reaction to the error, either return, die or trigger/callback - * @param int $level intensity of the error (PHP error code) - * @param mixed $debuginfo any information that can inform user as to nature of the error - */ - function XPath_Error($code = XPATH_ERROR, $mode = PEAR_ERROR_RETURN, + * Creates an XML_XPath error object, extending the PEAR_Error class + * + * @param int $code the xpath error code + * @param int $mode the reaction to the error, either return, die or trigger/callback + * @param int $level intensity of the error (PHP error code) + * @param mixed $debuginfo any information that can inform user as to nature of the error + * + * @access private + */ + function XML_XPath_Error($code = XML_XPATH_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null) { if (is_int($code)) { - $this->PEAR_Error(XPath::errorMessage($code), $code, $mode, $level, $debuginfo); + $this->PEAR_Error(XML_XPath::errorMessage($code), $code, $mode, $level, $debuginfo); } else { - $this->PEAR_Error("Invalid error code: $code", XPATH_ERROR, $mode, $level, $debuginfo); + $this->PEAR_Error("Invalid error code: $code", XML_XPATH_ERROR, $mode, $level, $debuginfo); } } Index: pear/XML_XPath/XPath/result.php diff -u pear/XML_XPath/XPath/result.php:1.6 pear/XML_XPath/XPath/result.php:1.7 --- pear/XML_XPath/XPath/result.php:1.6 Sat Mar 16 04:14:27 2002 +++ pear/XML_XPath/XPath/result.php Fri May 24 01:05:16 2002 @@ -17,7 +17,7 @@ // | Authors: Dan Allen <dan@mojavelinux.com> | // +----------------------------------------------------------------------+ -// $Id: result.php,v 1.6 2002/03/16 09:14:27 dallen Exp $ +// $Id: result.php,v 1.7 2002/05/24 05:05:16 dallen Exp $ // }}} // {{{ description @@ -27,30 +27,30 @@ // }}} // {{{ constants -define('XPATH_SORT_TEXT_ASCENDING', 1); -define('XPATH_SORT_NUMBER_ASCENDING', 2); -define('XPATH_SORT_NATURAL_ASCENDING', 3); -define('XPATH_SORT_TEXT_DESCENDING', 4); -define('XPATH_SORT_NUMBER_DESCENDING', 5); -define('XPATH_SORT_NATURAL_DESCENDING', 6); +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 XPath_result +// {{{ class XML_XPath_result /** - * Interface for an XPath result so that one can cycle through the result set and manipulate + * 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. * - * @version Revision: 1.1 + * @version Revision: 1.0 * @author Dan Allen <dan@mojavelinux.com> * @access public - * @since PHP 4.2 + * @since PHP 4.2.1 * @package XML_XPath */ // }}} -class XPath_result extends XPath_common { +class XML_XPath_result extends XML_XPath_common { // {{{ properties /** @var object reference to result object */ @@ -77,12 +77,12 @@ // }}} // {{{ constructor - function XPath_result($in_result, $in_query, &$in_xml, &$in_ctx) + function XML_XPath_result($in_result, $in_query, &$in_xml, &$in_ctx) { $this->result = &$in_result; $this->query = $in_query; $this->type = $this->result->type; - $this->data = $this->result->nodeset ? $this->result->nodeset : $this->result->value; + $this->data = isset($this->result->nodeset) ? $this->result->nodeset : $this->result->value; $this->index = 0; $this->xml = &$in_xml; $this->ctx = &$in_ctx; @@ -195,12 +195,12 @@ * @param mixed $in_index either an integer index or the string 'first' or 'last' * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ function setNodeIndex($in_index) { if (!$this->type == XPATH_NODESET) { - return PEAR::raiseError(null, XPATH_INVALID_NODESET, null, E_USER_NOTICE, "Cannot assign index $in_index to non-nodeset result in query {$this->query}", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODESET, null, E_USER_NOTICE, "Cannot assign index $in_index to non-nodeset result in query {$this->query}", 'XML_XPath_Error', true); } if ($in_index == 'last') { $this->index = sizeOf($this->data); @@ -210,13 +210,13 @@ } elseif (is_int($in_index)) { if ($in_index > sizeOf($this->data)) { - return PEAR::raiseError(null, XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Invalid index $in_index in query {$this->query}", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Invalid index $in_index in query {$this->query}", 'XML_XPath_Error', true); } elseif ($in_index > 0) { $this->index = $in_index; } else { - return PEAR::raiseError(null, XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Negative index $in_index is invalid", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_INDEX, null, E_USER_NOTICE, "Negative index $in_index is invalid", 'XML_XPath_Error', true); } } $this->pointer = $this->data[$this->index]; @@ -235,24 +235,24 @@ * ascending order. * * @param string $in_sortXpath relative xpath query location to each node in nodeset - * @param int $in_order either XPATH_SORT_TEXT_[DE|A]SCENDING, - * XPATH_SORT_NUMBER_[DE|A]SCENDING, - * XPATH_SORT_NATURAL_[DE|A]SCENDING + * @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 * * @access public - * @return void {or XPath_Error exception} + * @return void {or XML_XPath_Error exception} */ - function sort($in_sortXpath = '.', $in_order = XPATH_SORT_TEXT_ASCENDING) + function sort($in_sortXpath = '.', $in_order = XML_XPATH_SORT_TEXT_ASCENDING) { if ($this->resultType() != XPATH_NODESET) { - return PEAR::raiseError(null, XPATH_INVALID_NODESET, null, E_USER_NOTICE, $this->data, 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_NODESET, null, E_USER_NOTICE, $this->data, 'XPath_Error', true); } if ($in_sortXpath == '') { $in_sortXpath = '.'; } $xpathResult = @$this->ctx->xpath_eval($this->query . '/' . $in_sortXpath . '|' . $this->query); if (!$xpathResult || !$xpathResult->nodeset) { - return PEAR::raiseError(null, XPATH_INVALID_QUERY, null, E_USER_NOTICE, "Query {$this->query}/$in_sortXPath", 'XPath_Error', true); + return PEAR::raiseError(null, XML_XPATH_INVALID_QUERY, null, E_USER_NOTICE, "Query {$this->query}/$in_sortXPath", 'XML_XPath_Error', true); } $data = array(); $this->index = 0; @@ -263,41 +263,52 @@ } else { foreach ($xpathResult->nodeset as $index => $node) { - if ($node != $this->data[$this->index]) { + if (!isset($this->data[$this->index]) || $node != $this->data[$this->index]) { continue; } - if ($xpathResult->nodeset[$index + 1] == $this->data[$this->index]) { - array_push($data, ''); - } - elseif(isset($xpathResult->nodeset[$index + 1])) { - array_push($data, $xpathResult->nodeset[$index + 1]->get_content()); + + if (isset($xpathResult->nodeset[$index + 1])) { + if ($xpathResult->nodeset[$index + 1] == $this->data[$this->index]) { + array_push($data, ''); + } + else { + array_push($data, $xpathResult->nodeset[$index + 1]->get_content()); + } } + $this->index++; } } + switch ($in_order) { - case XPATH_SORT_TEXT_ASCENDING: + case XML_XPATH_SORT_TEXT_ASCENDING: asort($data, SORT_STRING); - break; - case XPATH_SORT_NUMBER_ASCENDING: + break; + + case XML_XPATH_SORT_NUMBER_ASCENDING: asort($data, SORT_NUMERIC); - break; - case XPATH_SORT_NATURAL_ASCENDING: + break; + + case XML_XPATH_SORT_NATURAL_ASCENDING: natsort($data); - break; - case XPATH_SORT_TEXT_DESCENDING: + break; + + case XML_XPATH_SORT_TEXT_DESCENDING: arsort($data, SORT_STRING); - break; - case XPATH_SORT_NUMBER_DESCENDING: + break; + + case XML_XPATH_SORT_NUMBER_DESCENDING: arsort($data, SORT_NUMERIC); - break; - case XPATH_SORT_NATURAL_DESCENDING: + break; + + case XML_XPATH_SORT_NATURAL_DESCENDING: natsort($data); $data = array_reverse($data, TRUE); - break; + break; + default: asort($data); - break; + break; } $dataReordered = array(); $this->index = 0;