3 * DOMIT! Lite is a non-validating, but lightweight and fast DOM parser for PHP
4 * @package domit-xmlparser
5 * @subpackage domit-xmlparser-lite
7 * @copyright (C) 2004 John Heinstein. All rights reserved
8 * @license http://www.gnu.org/copyleft/lesser.html LGPL License
9 * @author John Heinstein <johnkarl@nbnet.nb.ca>
10 * @link http://www.engageinteractive.com/domit/ DOMIT! Home Page
11 * DOMIT! is Free Software
14 if (!defined('DOMIT_INCLUDE_PATH')) {
15 define('DOMIT_INCLUDE_PATH', (dirname(__FILE__
) . "/"));
18 /** current version of DOMIT! Lite */
19 define ('DOMIT_LITE_VERSION', '0.18');
22 *@global array Flipped version of $definedEntities array, to allow two-way conversion of entities
24 * Made global so that Attr nodes, which have no ownerDocument property, can access the array
26 $GLOBALS['DOMIT_defined_entities_flip'] = array();
28 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_shared.php');
31 * The base class of all DOMIT node types
33 * @package domit-xmlparser
34 * @subpackage domit-xmlparser-lite
35 * @author John Heinstein <johnkarl@nbnet.nb.ca>
38 /** @var string The name of the node, varies according to node type */
40 /** @var string The value of the node, varies according to node type */
41 var $nodeValue = null;
42 /** @var int The type of node, e.g. CDataSection */
44 /** @var Object A reference to the parent of the current node */
45 var $parentNode = null;
46 /** @var Array An array of child node references */
47 var $childNodes = null;
48 /** @var Object A reference to the first node in the childNodes list */
49 var $firstChild = null;
50 /** @var Object A reference to the last node in the childNodes list */
51 var $lastChild = null;
52 /** @var Object A reference to the node prior to the current node in its parents childNodes list */
53 var $previousSibling = null;
54 /** @var Object A reference to the node after the current node in its parents childNodes list */
55 var $nextSibling = null;
56 /** @var Array An array of attribute key / value pairs */
57 var $attributes = null;
58 /** @var Object A reference to the Document node */
59 var $ownerDocument = null;
60 /** @var string The unique node id */
62 /** @var int The number of children of the current node */
66 * Raises error if abstract class is directly instantiated
68 function DOMIT_Node() {
69 DOMIT_DOMException
::raiseException(DOMIT_ABSTRACT_CLASS_INSTANTIATION_ERR
,
70 'Cannot instantiate abstract class DOMIT_Node');
74 * DOMIT_Node constructor, assigns a uid
76 function _constructor() {
78 $this->uid
= $uidFactory->generateUID();
82 * Appends a node to the childNodes list of the current node
84 * @param Object The node to be appended
85 * @return Object The appended node
87 function &appendChild(&$child) {
88 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
89 ('Method appendChild cannot be called by class ' . get_class($this)));
93 * Inserts a node to the childNodes list of the current node
95 * @param Object The node to be inserted
96 * @param Object The node before which the insertion is to occur
97 * @return Object The inserted node
99 function &insertBefore(&$newChild, &$refChild) {
100 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
101 ('Method insertBefore cannot be called by class ' . get_class($this)));
105 * Replaces a node with another
107 * @param Object The new node
108 * @param Object The old node
109 * @return Object The new node
111 function &replaceChild(&$newChild, &$oldChild) {
112 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
113 ('Method replaceChild cannot be called by class ' . get_class($this)));
117 * Removes a node from the childNodes list of the current node
119 * @param Object The node to be removed
120 * @return Object The removed node
122 function &removeChild(&$oldChild) {
123 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
124 ('Method removeChild cannot be called by class ' . get_class($this)));
128 * Returns the index of the specified node in a childNodes list
129 * @param Array The childNodes array to be searched
130 * @param Object The node targeted by the search
131 * @return int The index of the target node, or -1 if not found
133 function getChildNodeIndex(&$arr, &$child) {
135 $total = count($arr);
137 for ($i = 0; $i < $total; $i++
) {
138 if ($child->uid
== $arr[$i]->uid
) {
145 } //getChildNodeIndex
148 * Determines whether a node has any children
149 * @return boolean True if any child nodes are present
151 function hasChildNodes() {
152 return ($this->childCount
> 0);
156 * Copies a node and/or its children
158 * @param boolean True if all child nodes are also to be cloned
159 * @return Object A copy of the node and/or its children
161 function &cloneNode($deep = false) {
162 DOMIT_DOMException
::raiseException(DOMIT_ABSTRACT_METHOD_INVOCATION_ERR
,
163 'Cannot invoke abstract method DOMIT_Node->cloneNode($deep). Must provide an overridden method in your subclass.');
167 * Adds elements with the specified tag name to a NodeList collection
168 * @param Object The NodeList collection
169 * @param string The tag name of matching elements
171 function getNamedElements(&$nodeList, $tagName) {
172 //Implemented in DOMIT_Element.
173 //Needs to be here though! This is called against all nodes in the document.
177 * Sets the ownerDocument property of a node to the containing DOMIT_Document
178 * @param Object A reference to the document element of the DOMIT_Document
180 function setOwnerDocument(&$rootNode) {
181 if ($rootNode->ownerDocument
== null) {
182 unset($this->ownerDocument
);
183 $this->ownerDocument
= null;
186 $this->ownerDocument
=& $rootNode->ownerDocument
;
189 $total = $this->childCount
;
191 for ($i = 0; $i < $total; $i++
) {
192 $this->childNodes
[$i]->setOwnerDocument($rootNode);
197 * Tests whether a value is null, and if so, returns a default value
198 * @param mixed The value to be tested
199 * @param mixed The default value
200 * @return mixed The specified value, or the default value if null
202 function &nvl(&$value,$default) {
203 if (is_null($value)) return $default;
208 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like expression.
210 * @param string The query pattern
211 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node
212 * @return mixed A NodeList or single node that matches the pattern
214 function &getElementsByPath($pattern, $nodeIndex = 0) {
215 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
216 ('Method getElementsByPath cannot be called by class ' . get_class($this)));
217 } //getElementsByPath
220 * Returns the concatented text of the current node and its children
221 * @return string The concatented text of the current node and its children
224 return $this->nodeValue
;
228 * Formats a string for presentation as HTML
229 * @param string The string to be formatted
230 * @param boolean True if the string is to be sent directly to output
231 * @return string The HTML formatted string
233 function forHTML($str, $doPrint = false) {
234 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_utilities.php');
235 return DOMIT_Utilities
::forHTML($str, $doPrint);
239 * Generates an array representation of the node and its children
241 * @return Array A representation of the node and its children
244 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
245 ('Method toArray cannot be called by class ' . get_class($this)));
249 * A node event that can be set to fire upon document loading, used for node initialization
253 //you can override this method if you subclass any of the
254 //DOMIT_Nodes. It's a way of performing
255 //initialization of your subclass as soon as the document
256 //has been loaded (as opposed to as soon as the current node
257 //has been instantiated).
261 * Clears previousSibling, nextSibling, and parentNode references from a node that has been removed
263 function clearReferences() {
264 if ($this->previousSibling
!= null) {
265 unset($this->previousSibling
);
266 $this->previousSibling
= null;
268 if ($this->nextSibling
!= null) {
269 unset($this->nextSibling
);
270 $this->nextSibling
= null;
272 if ($this->parentNode
!= null) {
273 unset($this->parentNode
);
274 $this->parentNode
= null;
279 * Generates a normalized (formatted for readability) representation of the node and its children
280 * @param boolean True if HTML readable output is desired
281 * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities
282 * @return string The formatted string representation
284 function toNormalizedString($htmlSafe = false, $subEntities=false) {
285 //require this file for generating a normalized (readable) xml string representation
286 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_utilities.php');
287 global $DOMIT_defined_entities_flip;
289 $result = DOMIT_Utilities
::toNormalizedString($this, $subEntities, $DOMIT_defined_entities_flip);
291 if ($htmlSafe) $result = $this->forHTML($result);
294 } //toNormalizedString
299 * A parent class for nodes which possess child nodes
301 * @package domit-xmlparser
302 * @subpackage domit-xmlparser-lite
303 * @author John Heinstein <johnkarl@nbnet.nb.ca>
305 class DOMIT_ChildNodes_Interface
extends DOMIT_Node
{
307 * Raises error if abstract class is directly instantiated
309 function DOMIT_ChildNodes_Interface() {
310 DOMIT_DOMException
::raiseException(DOMIT_ABSTRACT_CLASS_INSTANTIATION_ERR
,
311 'Cannot instantiate abstract class DOMIT_ChildNodes_Interface');
312 } //DOMIT_ChildNodes_Interface
315 * Appends a node to the childNodes list of the current node
316 * @param Object The node to be appended
317 * @return Object The appended node
319 function &appendChild(&$child) {
320 if (!($this->hasChildNodes())) {
321 $this->childNodes
[0] =& $child;
322 $this->firstChild
=& $child;
325 //remove $child if it already exists
326 $index = $this->getChildNodeIndex($this->childNodes
, $child);
329 $this->removeChild($child);
333 $numNodes = $this->childCount
;
334 $prevSibling =& $this->childNodes
[($numNodes - 1)];
336 $this->childNodes
[$numNodes] =& $child;
338 //set next and previous relationships
339 $child->previousSibling
=& $prevSibling;
340 $prevSibling->nextSibling
=& $child;
343 $this->lastChild
=& $child;
344 $child->parentNode
=& $this;
346 unset($child->nextSibling
);
347 $child->nextSibling
= null;
349 $child->setOwnerDocument($this);
356 * Inserts a node to the childNodes list of the current node
357 * @param Object The node to be inserted
358 * @param Object The node before which the insertion is to occur
359 * @return Object The inserted node
361 function &insertBefore(&$newChild, &$refChild) {
362 if (($refChild->nodeType
== DOMIT_DOCUMENT_NODE
) ||
363 ($refChild->parentNode
== null)) {
365 DOMIT_DOMException
::raiseException(DOMIT_NOT_FOUND_ERR
,
366 'Reference child not present in the child nodes list.');
369 //if reference child is also the node to be inserted
370 //leave the document as is and don't raise an exception
371 if ($refChild->uid
== $newChild->uid
) {
375 //remove $newChild if it already exists
376 $index = $this->getChildNodeIndex($this->childNodes
, $newChild);
378 $this->removeChild($newChild);
381 //find index of $refChild in childNodes
382 $index = $this->getChildNodeIndex($this->childNodes
, $refChild);
385 //reset sibling chain
386 if ($refChild->previousSibling
!= null) {
387 $refChild->previousSibling
->nextSibling
=& $newChild;
388 $newChild->previousSibling
=& $refChild->previousSibling
;
391 $this->firstChild
=& $newChild;
393 if ($newChild->previousSibling
!= null) {
394 unset($newChild->previousSibling
);
395 $newChild->previousSibling
= null;
399 $newChild->parentNode
=& $refChild->parentNode
;
400 $newChild->nextSibling
=& $refChild;
401 $refChild->previousSibling
=& $newChild;
403 //add node to childNodes
404 $i = $this->childCount
;
408 $this->childNodes
[$i] =& $this->childNodes
[($i - 1)];
410 else if ($i == $index) {
411 $this->childNodes
[$i] =& $newChild;
419 $this->appendChild($newChild);
422 $newChild->setOwnerDocument($this);
428 * Replaces a node with another
429 * @param Object The new node
430 * @param Object The old node
431 * @return Object The new node
433 function &replaceChild(&$newChild, &$oldChild) {
434 if ($this->hasChildNodes()) {
435 //remove $newChild if it already exists
436 $index = $this->getChildNodeIndex($this->childNodes
, $newChild);
438 $this->removeChild($newChild);
441 //find index of $oldChild in childNodes
442 $index = $this->getChildNodeIndex($this->childNodes
, $oldChild);
445 $newChild->ownerDocument
=& $oldChild->ownerDocument
;
446 $newChild->parentNode
=& $oldChild->parentNode
;
448 //reset sibling chain
449 if ($oldChild->previousSibling
== null) {
450 unset($newChild->previousSibling
);
451 $newChild->previousSibling
= null;
454 $oldChild->previousSibling
->nextSibling
=& $newChild;
455 $newChild->previousSibling
=& $oldChild->previousSibling
;
458 if ($oldChild->nextSibling
== null) {
459 unset($newChild->nextSibling
);
460 $newChild->nextSibling
= null;
463 $oldChild->nextSibling
->previousSibling
=& $newChild;
464 $newChild->nextSibling
=& $oldChild->nextSibling
;
467 $this->childNodes
[$index] =& $newChild;
469 if ($index == 0) $this->firstChild
=& $newChild;
470 if ($index == ($this->childCount
- 1)) $this->lastChild
=& $newChild;
472 $newChild->setOwnerDocument($this);
478 DOMIT_DOMException
::raiseException(DOMIT_NOT_FOUND_ERR
,
479 ('Reference node for replaceChild not found.'));
483 * Removes a node from the childNodes list of the current node
484 * @param Object The node to be removed
485 * @return Object The removed node
487 function &removeChild(&$oldChild) {
488 if ($this->hasChildNodes()) {
489 //find index of $oldChild in childNodes
490 $index = $this->getChildNodeIndex($this->childNodes
, $oldChild);
493 //reset sibling chain
494 if (($oldChild->previousSibling
!= null) && ($oldChild->nextSibling
!= null)) {
495 $oldChild->previousSibling
->nextSibling
=& $oldChild->nextSibling
;
496 $oldChild->nextSibling
->previousSibling
=& $oldChild->previousSibling
;
498 else if (($oldChild->previousSibling
!= null) && ($oldChild->nextSibling
== null)) {
499 $this->lastChild
=& $oldChild->previousSibling
;
500 unset($oldChild->previousSibling
->nextSibling
);
501 $oldChild->previousSibling
->nextSibling
= null;
503 else if (($oldChild->previousSibling
== null) && ($oldChild->nextSibling
!= null)) {
504 unset($oldChild->nextSibling
->previousSibling
);
505 $oldChild->nextSibling
->previousSibling
= null;
506 $this->firstChild
=& $oldChild->nextSibling
;
508 else if (($oldChild->previousSibling
== null) && ($oldChild->nextSibling
== null)) {
509 unset($this->firstChild
);
510 $this->firstChild
= null;
511 unset($this->lastChild
);
512 $this->lastChild
= null;
515 $total = $this->childCount
;
517 //remove node from childNodes
518 for ($i = 0; $i < $total; $i++
) {
519 if ($i == ($total - 1)) {
520 array_splice($this->childNodes
, $i, 1);
522 else if ($i >= $index) {
523 $this->childNodes
[$i] =& $this->childNodes
[($i +
1)];
529 $oldChild->clearReferences();
534 DOMIT_DOMException
::raiseException(DOMIT_NOT_FOUND_ERR
,
535 ('Target node for removeChild not found.'));
539 * Searches the element tree for an element with the specified attribute name and value.
540 * @param string The value of the attribute
541 * @param string The name of the attribute
542 * @param boolean True if the first found node is to be returned as a node instead of a nodelist
543 * @return object A NodeList of found elements, or null
545 function &getElementsByAttribute($attrName = 'id', $attrValue = '',
546 $returnFirstFoundNode = false) {
547 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_nodemaps.php');
549 $nodelist =& new DOMIT_NodeList();
551 switch ($this->nodeType
) {
552 case DOMIT_ELEMENT_NODE
:
553 $this->_getElementsByAttribute($nodelist, $attrName = 'id', $attrValue,
554 $returnFirstFoundNode);
557 case DOMIT_DOCUMENT_NODE
:
558 if ($this->documentElement
!= null) {
559 $this->documentElement
->_getElementsByAttribute($nodelist,
560 $attrName, $attrValue, $returnFirstFoundNode);
565 if ($returnFirstFoundNode) {
566 if ($nodelist->getLength() > 0) {
567 return $nodelist->item(0);
576 } //getElementsByAttribute
579 * Searches the element tree for an element with the specified attribute name and value.
580 * @param object The node list of found elements
581 * @param string The value of the attribute
582 * @param string The name of the attribute
583 * @param boolean True if the first found node is to be returned as a node instead of a nodelist
584 * @param boolean True the node has been found
586 function _getElementsByAttribute(&$nodelist, $attrName, $attrValue,
587 $returnFirstFoundNode, $foundNode = false) {
588 if (!($foundNode && $returnFirstFoundNode)) {
589 if ($this->getAttribute($attrName) == $attrValue) {
590 $nodelist->appendNode($this);
592 if ($returnFirstFoundNode) return;
595 $total = $this->childCount
;
597 for ($i = 0; $i < $total; $i++
) {
598 $currNode =& $this->childNodes
[$i];
600 if ($currNode->nodeType
== DOMIT_ELEMENT_NODE
) {
601 $currNode->_getElementsByAttribute($nodelist,
602 $attrName, $attrValue,
603 $returnFirstFoundNode, $foundNode);
608 } //_getElementsByAttribute
609 } //DOMIT_ChildNodes_Interface
612 * A class representing the DOM Document
614 * @package domit-xmlparser
615 * @subpackage domit-xmlparser-lite
616 * @author John Heinstein <johnkarl@nbnet.nb.ca>
618 class DOMIT_Lite_Document
extends DOMIT_ChildNodes_Interface
{
619 /** @var string The xml declaration text */
621 /** @var string The doctype text */
623 /** @var Object A reference to the root node of the DOM document */
624 var $documentElement;
625 /** @var string The parser used to process the DOM document, either "EXPAT" or "SAXY_LITE" */
627 /** @var Object A reference to the DOMIT_DOMImplementation object */
629 /** @var Array User defined translation table for XML entities */
630 var $definedEntities = array();
631 /** @var boolean If true, loadXML or parseXML will attempt to detect and repair invalid xml */
632 var $doResolveErrors = false;
633 /** @var boolean If true, elements tags will be rendered to string as <element></element> rather than <element/> */
634 var $doExpandEmptyElementTags = false;
635 /** @var array A list of exceptions to the empty element expansion rule */
636 var $expandEmptyElementExceptions = array();
637 /** @var int The error code returned by the SAX parser */
639 /** @var string The error string returned by the SAX parser */
640 var $errorString = '';
641 /** @var object A reference to a http connection or proxy server, if one is required */
642 var $httpConnection = null;
645 * DOM Document constructor
647 function DOMIT_Lite_Document() {
648 $this->_constructor();
649 $this->xmlDeclaration
= '';
651 $this->documentElement
= null;
652 $this->nodeType
= DOMIT_DOCUMENT_NODE
;
653 $this->nodeName
= '#document';
654 $this->ownerDocument
=& $this;
656 $this->implementation
=& new DOMIT_DOMImplementation();
657 } //DOMIT_Lite_Document
660 * Specifies whether DOMIT! Lite will try to fix invalid XML before parsing begins
661 * @param boolean True if errors are to be resolved
663 function resolveErrors($truthVal) {
664 $this->doResolveErrors
= $truthVal;
668 * Specifies the parameters of the http conection used to obtain the xml data
669 * @param string The ip address or domain name of the connection
670 * @param string The path of the connection
671 * @param int The port that the connection is listening on
672 * @param int The timeout value for the connection
673 * @param string The user name, if authentication is required
674 * @param string The password, if authentication is required
676 function setConnection($host, $path = '/', $port = 80, $timeout = 0, $user = null, $password = null) {
677 require_once(DOMIT_INCLUDE_PATH
. 'php_http_client_generic.php');
679 $this->httpConnection
=& new php_http_client_generic($host, $path, $port, $timeout, $user, $password);
683 * Specifies basic authentication for an http connection
684 * @param string The user name
685 * @param string The password
687 function setAuthorization($user, $password) {
688 $this->httpConnection
->setAuthorization($user, $password);
692 * Specifies that a proxy is to be used to obtain the xml data
693 * @param string The ip address or domain name of the proxy
694 * @param string The path to the proxy
695 * @param int The port that the proxy is listening on
696 * @param int The timeout value for the connection
697 * @param string The user name, if authentication is required
698 * @param string The password, if authentication is required
700 function setProxyConnection($host, $path = '/', $port = 80, $timeout = 0, $user = null, $password = null) {
701 require_once(DOMIT_INCLUDE_PATH
. 'php_http_proxy.php');
703 $this->httpConnection
=& new php_http_proxy($host, $path, $port, $timeout, $user, $password);
704 } //setProxyConnection
707 * Specifies basic authentication for the proxy
708 * @param string The user name
709 * @param string The password
711 function setProxyAuthorization($user, $password) {
712 $this->httpConnection
->setProxyAuthorization($user, $password);
713 } //setProxyAuthorization
716 * Returns the error code from the underlying SAX parser
717 * @return int The error code
719 function getErrorCode() {
720 return $this->errorCode
;
724 * Returns the error string from the underlying SAX parser
725 * @return string The error string
727 function getErrorString() {
728 return $this->errorString
;
732 * Specifies whether elements tags will be rendered to string as <element></element> rather than <element/>
733 * @param boolean True if the expanded form is to be used
734 * @param mixed An array of tag names that should be excepted from expandEmptyElements rule (optional)
736 function expandEmptyElementTags($truthVal, $expandEmptyElementExceptions = false) {
737 $this->doExpandEmptyElementTags
= $truthVal;
739 if (is_array($expandEmptyElementExceptions)) {
740 $this->expandEmptyElementExceptions
= $expandEmptyElementExceptions;
742 } //expandEmptyElementTags
745 * Set the specified node as document element
746 * @param Object The node that is to become document element
747 * @return Object The new document element
749 function &setDocumentElement(&$node) {
750 if ($node->nodeType
== DOMIT_ELEMENT_NODE
) {
751 if ($this->documentElement
== null) {
752 parent
::appendChild($node);
755 parent
::replaceChild($node, $this->documentElement
);
758 $this->documentElement
=& $node;
761 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
762 ('Cannot add a node of type ' . get_class($node) . ' as a Document Element.'));
766 } //setDocumentElement
769 * Appends a node to the childNodes list of the current node
770 * @param Object The node to be appended
771 * @return Object The appended node
773 function &appendChild(&$node) {
774 if ($node->nodeType
== DOMIT_ELEMENT_NODE
) {
775 if ($this->documentElement
== null) {
776 parent
::appendChild($node);
777 $this->setDocumentElement($node);
780 //error thrown if documentElement already exists!
781 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
782 ('Cannot have more than one root node (documentElement) in a DOMIT_Document.'));
786 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
787 ('Cannot add a node of type ' . get_class($node) . ' to a DOMIT_Document.'));
794 * Replaces a node with another
795 * @param Object The new node
796 * @param Object The old node
797 * @return Object The new node
799 function &replaceChild(&$newChild, &$oldChild) {
800 if (($this->documentElement
!= null) && ($oldChild->uid
== $this->documentElement
->uid
)) {
801 if ($node->nodeType
== DOMIT_ELEMENT_NODE
) {
802 //replace documentElement with new node
803 $this->setDocumentElement($newChild);
806 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
807 ('Cannot replace Document Element with a node of class ' . get_class($newChild)));
811 if ($node->nodeType
== DOMIT_ELEMENT_NODE
) {
812 if ($this->documentElement
!= null) {
813 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
814 ('Cannot have more than one root node (documentElement) in a DOMIT_Document.'));
817 parent
::replaceChild($newChild, $oldChild);
821 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
822 ('Nodes of class ' . get_class($newChild) . ' cannot be children of a DOMIT_Document.'));
830 * Inserts a node to the childNodes list of the current node
831 * @param Object The node to be inserted
832 * @param Object The node before which the insertion is to occur
833 * @return Object The inserted node
835 function &insertBefore(&$newChild, &$refChild) {
836 $type = $newChild->nodeType
;
838 if ($type == DOMIT_ELEMENT_NODE
) {
839 if ($this->documentElement
== null) {
840 parent
::insertBefore($newChild);
841 $this->setDocumentElement($newChild);
844 //error thrown if documentElement already exists!
845 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
846 ('Cannot have more than one root node (documentElement) in a DOMIT_Document.'));
850 DOMIT_DOMException
::raiseException(DOMIT_HIERARCHY_REQUEST_ERR
,
851 ('Cannot insert a node of type ' . get_class($newChild) . ' to a DOMIT_Document.'));
858 * Removes a node from the childNodes list of the current node
859 * @param Object The node to be removed
860 * @return Object The removed node
862 function &removeChild(&$oldChild) {
863 if (($this->documentElement
!= null) && ($oldChild->uid
== $this->documentElement
->uid
)) {
864 parent
::removeChild($oldChild);
865 $this->documentElement
= null;
868 parent
::removeChild($oldChild);
871 $oldChild->clearReferences();
876 * Creates a new DOMIT_Element node
877 * @param string The tag name of the element
878 * @return Object The new element
880 function &createElement($tagName) {
881 $node =& new DOMIT_Element($tagName);
882 $node->ownerDocument
=& $this;
888 * Creates a new DOMIT_Text node
889 * @param string The text of the node
890 * @return Object The new text node
892 function &createTextNode($data) {
893 $node =& new DOMIT_TextNode($data);
894 $node->ownerDocument
=& $this;
900 * Creates a new DOMIT_CDataSection node
901 * @param string The text of the CDATASection
902 * @return Object The new CDATASection node
904 function &createCDATASection($data) {
905 $node =& new DOMIT_CDATASection($data);
906 $node->ownerDocument
=& $this;
909 } //createCDATASection
912 * Retrieves a NodeList of child elements with the specified tag name
913 * @param string The matching element tag name
914 * @return Object A NodeList of found elements
916 function &getElementsByTagName($tagName) {
917 $nodeList =& new DOMIT_NodeList();
919 if ($this->documentElement
!= null) {
920 $this->documentElement
->getNamedElements($nodeList, $tagName);
924 } //getElementsByTagName
927 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like expression.
928 * @param string The query pattern
929 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node
930 * @return mixed A NodeList or single node that matches the pattern
932 function &getElementsByPath($pattern, $nodeIndex = 0) {
933 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_getelementsbypath.php');
935 $gebp = new DOMIT_GetElementsByPath();
936 $myResponse =& $gebp->parsePattern($this, $pattern, $nodeIndex);
939 } //getElementsByPath
942 * Parses an xml string; first encodes string as UTF-8
943 * @param string The xml text to be parsed
944 * @param boolean True if SAXY is to be used instead of Expat
945 * @param boolean False if CDATA Section are to be generated as Text nodes
946 * @param boolean True if onLoad is to be called on each node after parsing
947 * @return boolean True if parsing is successful
949 function parseXML_utf8($xmlText, $useSAXY = true, $preserveCDATA = true, $fireLoadEvent = false) {
950 return $this->parseXML(utf8_encode($xmlText), $useSAXY, $preserveCDATA, $fireLoadEvent);
954 * Parses an xml string
955 * @param string The xml text to be parsed
956 * @param boolean True if SAXY is to be used instead of Expat
957 * @param boolean False if CDATA Section are to be generated as Text nodes
958 * @param boolean True if onLoad is to be called on each node after parsing
959 * @return boolean True if parsing is successful
961 function parseXML($xmlText, $useSAXY = true, $preserveCDATA = true, $fireLoadEvent = false) {
962 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_utilities.php');
964 if ($this->doResolveErrors
) {
965 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_doctor.php');
966 $xmlText = DOMIT_Doctor
::fixAmpersands($xmlText);
969 if (DOMIT_Utilities
::validateXML($xmlText)) {
970 $domParser =& new DOMIT_Parser();
972 if ($useSAXY ||
(!function_exists('xml_parser_create'))) {
973 //use SAXY parser to populate xml tree
974 $this->parser
= 'SAXY_LITE';
975 $success = $domParser->parseSAXY($this, $xmlText, $preserveCDATA, $this->definedEntities
);
978 //use Expat parser to populate xml tree
979 $this->parser
= 'EXPAT';
980 $success = $domParser->parse($this, $xmlText, $preserveCDATA);
983 if ($fireLoadEvent && ($this->documentElement
!= null)) $this->load($this->documentElement
);
993 * Parses an xml file; first encodes text as UTF-8
994 * @param string The xml file to be parsed
995 * @param boolean True if SAXY is to be used instead of Expat
996 * @param boolean False if CDATA Section are to be generated as Text nodes
997 * @param boolean True if onLoad is to be called on each node after parsing
998 * @return boolean True if parsing is successful
1000 function loadXML_utf8($filename, $useSAXY = true, $preserveCDATA = true, $fireLoadEvent = false) {
1001 $xmlText = $this->getTextFromFile($filename);
1002 return $this->parseXML_utf8($xmlText, $useSAXY, $preserveCDATA, $fireLoadEvent);
1006 * Parses an xml file
1007 * @param string The xml file to be parsed
1008 * @param boolean True if SAXY is to be used instead of Expat
1009 * @param boolean False if CDATA Section are to be generated as Text nodes
1010 * @param boolean True if onLoad is to be called on each node after parsing
1011 * @return boolean True if parsing is successful
1013 function loadXML($filename, $useSAXY = true, $preserveCDATA = true, $fireLoadEvent = false) {
1014 $xmlText = $this->getTextFromFile($filename);
1015 return $this->parseXML($xmlText, $useSAXY, $preserveCDATA, $fireLoadEvent);
1019 * Retrieves text from a file
1020 * @param string The file path
1021 * @return string The text contained in the file
1023 function getTextFromFile($filename) {
1024 if ($this->httpConnection
!= null) {
1025 $response =& $this->httpConnection
->get($filename);
1026 $this->httpConnection
->disconnect();
1027 return $response->getResponse();
1029 else if (function_exists('file_get_contents')) {
1030 //if (file_exists($filename)) {
1031 return file_get_contents($filename);
1035 require_once(DOMIT_INCLUDE_PATH
. 'php_file_utilities.php');
1037 $fileContents =& php_file_utilities
::getDataFromFile($filename, 'r');
1038 return $fileContents;
1045 * Saves the current DOM document as an xml file; first encodes text as UTF-8
1046 * @param string The path of the xml file
1047 * @param boolean True if xml text is to be normalized before saving
1048 * @return boolean True if save is successful
1050 function saveXML_utf8($filename, $normalized=false) {
1052 $stringRep = $this->toNormalizedString(false, true); //param 2 is $subEntities
1055 $stringRep = $this->toString(false, true);
1058 return $this->saveTextToFile($filename, utf8_encode($stringRep));
1062 * Saves the current DOM document as an xml file
1063 * @param string The path of the xml file
1064 * @param boolean True if xml text is to be normalized before saving
1065 * @return boolean True if save is successful
1067 function saveXML($filename, $normalized=false) {
1069 $stringRep = $this->toNormalizedString(false, true);
1072 $stringRep = $this->toString(false, true);
1075 return $this->saveTextToFile($filename, $stringRep);
1079 * Saves text to a file
1080 * @param string The file path
1081 * @param string The text to be saved
1082 * @return boolean True if the save is successful
1084 function saveTextToFile($filename, $text) {
1085 if (function_exists('file_put_contents')) {
1086 file_put_contents($filename, $text);
1089 require_once(DOMIT_INCLUDE_PATH
. 'php_file_utilities.php');
1090 php_file_utilities
::putDataToFile($filename, $text, 'w');
1093 return (file_exists($filename) && is_writable($filename));
1097 * Indicates the SAX parser used to parse the current document
1098 * @return string Either "SAXY_LITE" or "EXPAT"
1100 function parsedBy() {
1101 return $this->parser
;
1105 * Returns the concatented text of the current node and its children
1106 * @return string The concatented text of the current node and its children
1108 function getText() {
1109 if ($this->documentElement
!= null) {
1110 $root =& $this->documentElement
;
1111 return $root->getText();
1119 * Returns the doctype text
1120 * @return string The doctype text, or an emty string
1122 function getDocType() {
1123 return $this->doctype
;
1127 * Returns the xml declaration text
1128 * @return mixed The xml declaration text, or an empty string
1130 function getXMLDeclaration() {
1131 return $this->xmlDeclaration
;
1132 } //getXMLDeclaration
1135 * Returns a reference to the DOMIT_DOMImplementation object
1136 * @return Object A reference to the DOMIT_DOMImplementation object
1138 function &getDOMImplementation() {
1139 return $this->implementation
;
1140 } //getDOMImplementation
1143 * Manages the firing of the onLoad() event
1144 * @param Object The parent node of the current recursion
1146 function load(&$contextNode) {
1147 $total = $contextNode->childCount
;
1149 for ($i = 0; $i < $total; $i++
) {
1150 $currNode =& $contextNode->childNodes
[$i];
1151 $currNode->ownerDocument
->load($currNode);
1154 $contextNode->onLoad();
1158 * Returns the current version of DOMIT! Lite
1159 * @return Object The current version of DOMIT! Lite
1161 function getVersion() {
1162 return DOMIT_LITE_VERSION
;
1166 * Appends an array of entity mappings to the existing translation table
1168 * Intended mainly to facilitate the conversion of non-ASCII entities into equivalent characters
1170 * @param array A list of entity mappings in the format: array('&' => '&');
1172 function appendEntityTranslationTable($table) {
1173 $this->definedEntities
= $table;
1175 global $DOMIT_defined_entities_flip;
1176 $DOMIT_defined_entities_flip = array_flip($table);
1177 } //appendEntityTranslationTable
1180 * Generates an array representation of the node and its children
1181 * @return Array A representation of the node and its children
1183 function toArray() {
1184 $arReturn = array($this->nodeName
=> array());
1185 $total = $this->childCount
;
1187 for ($i = 0; $i < $total; $i++
) {
1188 $arReturn[$this->nodeName
][$i] = $this->childNodes
[$i]->toArray();
1195 * Copies a node and/or its children
1196 * @param boolean True if all child nodes are also to be cloned
1197 * @return Object A copy of the node and/or its children
1199 function &cloneNode($deep = false) {
1200 $className = get_class($this);
1201 $clone =& new $className($this->nodeName
);
1204 $total = $this->childCount
;
1206 for ($i = 0; $i < $total; $i++
) {
1207 $currentChild =& $this->childNodes
[$i];
1208 $clone->appendChild($currentChild->cloneNode($deep));
1216 * Generates a string representation of the node and its children
1217 * @param boolean True if HTML readable output is desired
1218 * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities
1219 * @return string The string representation
1221 function toString($htmlSafe = false, $subEntities=false) {
1223 $total = $this->childCount
;
1225 for ($i = 0; $i < $total; $i++
) {
1226 $result .= $this->childNodes
[$i]->toString(false, $subEntities);
1229 if ($htmlSafe) $result = $this->forHTML($result);
1233 } //DOMIT_Lite_Document
1236 * A class representing the DOM Element
1238 * @package domit-xmlparser
1239 * @subpackage domit-xmlparser-lite
1240 * @author John Heinstein <johnkarl@nbnet.nb.ca>
1242 class DOMIT_Element
extends DOMIT_ChildNodes_Interface
{
1244 * DOM Element constructor
1245 * @param string The tag name of the element
1247 function DOMIT_Element($tagName) {
1248 $this->_constructor();
1249 $this->nodeType
= DOMIT_ELEMENT_NODE
;
1250 $this->nodeName
= $tagName;
1251 $this->attributes
= array();
1252 $this->childNodes
= array();
1256 * Returns the tag name of the element
1257 * @return string The tag name of the element
1259 function getTagName() {
1260 return $this->nodeName
;
1264 * Adds elements with the specified tag name to a NodeList collection
1265 * @param Object The NodeList collection
1266 * @param string The tag name of matching elements
1268 function getNamedElements(&$nodeList, $tagName) {
1269 if (($this->nodeName
== $tagName) ||
($tagName == '*')) {
1270 $nodeList->appendNode($this);
1273 $total = $this->childCount
;
1275 for ($i = 0; $i < $total; $i++
) {
1276 $this->childNodes
[$i]->getNamedElements($nodeList, $tagName);
1278 } //getNamedElements
1281 * Returns the concatented text of the current node and its children
1282 * @return string The concatented text of the current node and its children
1284 function getText() {
1286 $numChildren = $this->childCount
;
1288 for ($i = 0; $i < $numChildren; $i++
) {
1289 $child =& $this->childNodes
[$i];
1290 $text .= $child->getText();
1297 * If a child text node exists, sets the nodeValue to $data. A child text node is created if none exists
1298 * @param string The text data of the node
1300 function setText($data) {
1301 switch ($this->childCount
) {
1303 if ($this->firstChild
->nodeType
== DOMIT_TEXT_NODE
) {
1304 $this->firstChild
->setText($data);
1309 $childTextNode =& $this->ownerDocument
->createTextNode($data);
1310 $this->appendChild($childTextNode);
1314 //do nothing. Maybe throw error???
1319 * Retrieves a NodeList of child elements with the specified tag name
1320 * @param string The matching element tag name
1321 * @return Object A NodeList of found elements
1323 function &getElementsByTagName($tagName) {
1324 $nodeList =& new DOMIT_NodeList();
1325 $this->getNamedElements($nodeList, $tagName);
1328 } //getElementsByTagName
1331 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like expression.
1332 * @param string The query pattern
1333 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node
1334 * @return mixed A NodeList or single node that matches the pattern
1336 function &getElementsByPath($pattern, $nodeIndex = 0) {
1337 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_getelementsbypath.php');
1339 $gebp = new DOMIT_GetElementsByPath();
1340 $myResponse =& $gebp->parsePattern($this, $pattern, $nodeIndex);
1343 } //getElementsByPath
1346 * Gets the value of the specified attribute, if it exists
1347 * @param string The attribute name
1348 * @return string The attribute value
1350 function getAttribute($name) {
1351 if ($this->hasAttribute($name)) {
1352 return $this->attributes
[$name];
1357 * Sets the value of the specified attribute; creates a new attribute if one doesn't exist
1358 * @param string The attribute name
1359 * @param string The desired attribute value
1361 function setAttribute($name, $value) {
1362 $this->attributes
[$name] = $value;
1366 * Removes the specified attribute
1367 * @param string The name of the attribute to be removed
1369 function removeAttribute($name) {
1370 if ($this->hasAttribute($name)) {
1371 unset($this->attributes
[$name]);
1376 * Determines whether an attribute with the specified name exists
1377 * @param string The name of the attribute
1378 * @return boolean True if the attribute exists
1380 function hasAttribute($name) {
1381 return isset($this->attributes
[$name]);
1385 * Collapses adjacent text nodes in entire element subtree
1387 function normalize() {
1388 if ($this->hasChildNodes()) {
1389 $currNode =& $this->childNodes
[0];
1391 while ($currNode->nextSibling
!= null) {
1392 $nextNode =& $currNode->nextSibling
;
1394 if (($currNode->nodeType
== DOMIT_TEXT_NODE
) &&
1395 ($nextNode->nodeType
== DOMIT_TEXT_NODE
)) {
1396 $currNode->nodeValue
.= $nextNode->nodeValue
;
1397 $this->removeChild($nextNode);
1400 $currNode->normalize();
1403 if ($currNode->nextSibling
!= null) {
1404 $currNode =& $currNode->nextSibling
;
1411 * Generates an array representation of the node and its children
1412 * @return Array A representation of the node and its children
1414 function toArray() {
1415 $arReturn = array($this->nodeName
=> array("attributes" => $this->attributes
));
1416 $total = $this->childCount
;
1418 for ($i = 0; $i < $total; $i++
) {
1419 $arReturn[$this->nodeName
][$i] = $this->childNodes
[$i]->toArray();
1426 * Copies a node and/or its children
1427 * @param boolean True if all child nodes are also to be cloned
1428 * @return Object A copy of the node and/or its children
1430 function &cloneNode($deep = false) {
1431 $className = get_class($this);
1432 $clone =& new $className($this->nodeName
);
1434 $clone->attributes
= $this->attributes
;
1437 $total = $this->childCount
;
1439 for ($i = 0; $i < $total; $i++
) {
1440 $currentChild =& $this->childNodes
[$i];
1441 $clone->appendChild($currentChild->cloneNode($deep));
1449 * Generates a string representation of the node and its children
1450 * @param boolean True if HTML readable output is desired
1451 * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities
1452 * @return string The string representation
1454 function toString($htmlSafe = false, $subEntities=false) {
1455 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_utilities.php');
1456 global $DOMIT_defined_entities_flip;
1458 $result = '<' . $this->nodeName
;
1461 foreach ($this->attributes
as $key => $value) {
1462 $result .= ' ' . $key . '="';
1463 $result .= ($subEntities ? DOMIT_Utilities
::convertEntities($value,
1464 $DOMIT_defined_entities_flip) : $value);
1469 $myNodes =& $this->childNodes
;
1470 $total = count($myNodes);
1475 for ($i = 0; $i < $total; $i++
) {
1476 $child =& $myNodes[$i];
1477 $result .= $child->toString(false, $subEntities);
1480 $result .= '</' . $this->nodeName
. '>';
1483 if ($this->ownerDocument
->doExpandEmptyElementTags
) {
1484 if (in_array($this->nodeName
, $this->ownerDocument
->expandEmptyElementExceptions
)) {
1488 $result .= '></' . $this->nodeName
. '>';
1492 if (in_array($this->nodeName
, $this->ownerDocument
->expandEmptyElementExceptions
)) {
1493 $result .= '></' . $this->nodeName
. '>';
1501 if ($htmlSafe) $result = $this->forHTML($result);
1508 * A class representing the DOM Text Node
1510 * @package domit-xmlparser
1511 * @subpackage domit-xmlparser-lite
1512 * @author John Heinstein <johnkarl@nbnet.nb.ca>
1514 class DOMIT_TextNode
extends DOMIT_Node
{
1516 * DOM Text Node constructor
1517 * @param string The text of the node
1519 function DOMIT_TextNode($data) {
1520 $this->_constructor();
1521 $this->nodeType
= DOMIT_TEXT_NODE
;
1522 $this->nodeName
= '#text';
1523 $this->setText($data);
1527 * Returns the text contained in the current node
1528 * @return string The text of the current node
1530 function getText() {
1531 return $this->nodeValue
;
1535 * Sets the text contained in the current node to $data.
1536 * @param string The text data of the node
1538 function setText($data) {
1539 $this->nodeValue
= $data;
1543 * Generates an array representation of the node and its children
1544 * @return Array A representation of the node and its children
1546 function toArray() {
1547 return $this->toString();
1551 * Copies a node and/or its children
1552 * @param boolean True if all child nodes are also to be cloned
1553 * @return Object A copy of the node and/or its children
1555 function &cloneNode($deep = false) {
1556 $className = get_class($this);
1557 $clone =& new $className($this->nodeValue
);
1563 * Generates a string representation of the node and its children
1564 * @param boolean True if HTML readable output is desired
1565 * @param boolean True if illegal xml characters should be converted to entities
1566 * @return string The string representation
1568 function toString($htmlSafe = false, $subEntities=false) {
1569 require_once(DOMIT_INCLUDE_PATH
. 'xml_domit_utilities.php');
1570 global $DOMIT_defined_entities_flip;
1572 $result = ($subEntities ? DOMIT_Utilities
::convertEntities($this->nodeValue
,
1573 $DOMIT_defined_entities_flip) : $this->nodeValue
);
1575 if ($htmlSafe) $result = $this->forHTML($result);
1582 * A class representing the DOM CDATA Section
1584 * @package domit-xmlparser
1585 * @subpackage domit-xmlparser-lite
1586 * @author John Heinstein <johnkarl@nbnet.nb.ca>
1588 class DOMIT_CDATASection
extends DOMIT_TextNode
{
1590 * DOM CDATA Section node constructor
1591 * @param string The text of the node
1593 function DOMIT_CDATASection($data) {
1594 $this->_constructor();
1595 $this->nodeType
= DOMIT_CDATA_SECTION_NODE
;
1596 $this->nodeName
= '#cdata-section';
1597 $this->setText($data);
1598 } //DOMIT_CDATASection
1601 * Generates a string representation of the node and its children
1602 * @param boolean True if HTML readable output is desired
1603 * @param boolean True if illegal xml characters should be converted to entities
1604 * @return string The string representation
1606 function toString($htmlSafe = false, $subEntities=false) {
1607 $result = '<![CDATA[';
1608 $result .= $subEntities ?
str_replace("]]>", "]]>", $this->nodeValue
) :
1612 if ($htmlSafe) $result = $this->forHTML($result);
1616 } //DOMIT_CDATASection
1619 * Manages the generation of a DOMIT! document from SAX events
1621 * @package domit-xmlparser
1622 * @subpackage domit-xmlparser-lite
1623 * @author John Heinstein <johnkarl@nbnet.nb.ca>
1625 class DOMIT_Parser
{
1626 /** @var Object A reference to the resulting xmldoc */
1628 /** @var Object A reference to the current node in the parsing process */
1629 var $currentNode = null;
1630 /** @var Object A reference to the last child in the parsing process */
1631 var $lastChild = null;
1632 /** @var boolean True if currently parsing a CDATA Section */
1633 var $inCDATASection = false; //flag for Expat
1634 /** @var boolean True if currently parsing a Text node */
1635 var $inTextNode = false;
1636 /** @var boolean True is CDATA Section nodes are not to be converted into Text nodes */
1638 /** @var string A container for holding the currently parsed text data */
1639 var $parseContainer = '';
1640 /** @var string The current docutype text */
1641 var $parseItem = '';
1644 * Parses xml text using Expat
1645 * @param Object A reference to the DOM document that the xml is to be parsed into
1646 * @param string The text to be parsed
1647 * @param boolean True if CDATA Section nodes are not to be converted into Text nodes
1648 * @return boolean True if the parsing is successful
1650 function parse (&$myXMLDoc, $xmlText, $preserveCDATA = true) {
1651 $this->xmlDoc
=& $myXMLDoc;
1652 $this->lastChild
=& $this->xmlDoc
;
1654 $this->preserveCDATA
= $preserveCDATA;
1656 //create instance of expat parser (should be included in php distro)
1657 if (version_compare(phpversion(), '5.0', '<=')) {
1658 $parser =& xml_parser_create('');
1661 $parser =& xml_parser_create();
1664 //set handlers for SAX events
1665 xml_set_object($parser, $this);
1666 xml_set_element_handler($parser, 'startElement', 'endElement');
1667 xml_set_character_data_handler($parser, 'dataElement');
1668 xml_set_default_handler($parser, 'defaultDataElement');
1669 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING
, 0);
1670 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE
, 1);
1672 //parse out whitespace - (XML_OPTION_SKIP_WHITE = 1 does not
1673 //seem to work consistently across versions of PHP and Expat
1674 $xmlText = eregi_replace('>' . "[[:space:]]+" . '<' , '><', $xmlText);
1676 $success = xml_parse($parser, $xmlText);
1678 $this->xmlDoc
->errorCode
= xml_get_error_code($parser);
1679 $this->xmlDoc
->errorString
= xml_error_string($this->xmlDoc
->errorCode
);
1681 xml_parser_free($parser);
1687 * Parses xml text using SAXY
1688 * @param Object A reference to the DOM document that the xml is to be parsed into
1689 * @param string The text to be parsed
1690 * @param boolean True if CDATA Section nodes are not to be converted into Text nodes
1691 * @return boolean True if the parsing is successful
1693 function parseSAXY(&$myXMLDoc, $xmlText, $preserveCDATA, $definedEntities) {
1694 require_once(DOMIT_INCLUDE_PATH
. 'xml_saxy_lite_parser.php');
1696 $this->xmlDoc
=& $myXMLDoc;
1697 $this->lastChild
=& $this->xmlDoc
;
1699 //create instance of SAXY parser
1700 $parser =& new SAXY_Lite_Parser();
1701 $parser->appendEntityTranslationTable($definedEntities);
1703 $parser->xml_set_element_handler(array(&$this, 'startElement'), array(&$this, 'endElement'));
1704 $parser->xml_set_character_data_handler(array(&$this, 'dataElement'));
1706 if ($preserveCDATA) {
1707 $parser->xml_set_cdata_section_handler(array(&$this, 'cdataElement'));
1710 $success = $parser->parse($xmlText);
1712 $this->xmlDoc
->errorCode
= $parser->xml_get_error_code();
1713 $this->xmlDoc
->errorString
= $parser->xml_error_string($this->xmlDoc
->errorCode
);
1719 * Generates and appends a new text node from the parseContainer text
1721 function dumpTextNode() {
1722 //traps for mixed content
1723 $currentNode =& $this->xmlDoc
->createTextNode($this->parseContainer
);
1724 $this->lastChild
->appendChild($currentNode);
1725 $this->inTextNode
= false;
1726 $this->parseContainer
= '';
1730 * Catches a start element event and processes the data
1731 * @param Object A reference to the current SAX parser
1732 * @param string The tag name of the current element
1733 * @param Array An array of the element attributes
1735 function startElement(&$parser, $name, $attrs) {
1736 if ($this->inTextNode
) {
1737 $this->dumpTextNode();
1740 $currentNode =& $this->xmlDoc
->createElement($name);
1741 $currentNode->attributes
= $attrs;
1742 $this->lastChild
->appendChild($currentNode);
1743 $this->lastChild
=& $currentNode;
1747 * Catches an end element event and processes the data
1748 * @param Object A reference to the current SAX parser
1749 * @param string The tag name of the current element
1751 function endElement(&$parser, $name) {
1752 if ($this->inTextNode
) {
1753 $this->dumpTextNode();
1756 $this->lastChild
=& $this->lastChild
->parentNode
;
1760 * Catches a data event and processes the text
1761 * @param Object A reference to the current SAX parser
1762 * @param string The current text data
1764 function dataElement(&$parser, $data) {
1765 if (!$this->inCDATASection
) $this->inTextNode
= true;
1767 $this->parseContainer
.= $data;
1771 * Catches a CDATA Section event and processes the text
1772 * @param Object A reference to the current SAX parser
1773 * @param string The current text data
1775 function cdataElement(&$parser, $data) {
1776 $currentNode =& $this->xmlDoc
->createCDATASection($data);
1778 $this->lastChild
->appendChild($currentNode);
1782 * Catches a default data event and processes the data
1783 * @param Object A reference to the current SAX parser
1784 * @param string The current data
1786 function defaultDataElement(&$parser, $data) {
1787 if (strlen($data) > 2){
1788 $pre = strtoupper(substr($data, 0, 3));
1791 case '<![': //cdata section coming
1792 if ($this->preserveCDATA
) {
1793 $this->inCDATASection
= true;
1796 case ']]>': //cdata remnant - ignore
1797 $currentNode =& $this->xmlDoc
->createCDATASection($this->parseContainer
);
1798 $this->lastChild
->appendChild($currentNode);
1799 $this->inCDATASection
= false;
1800 $this->parseContainer
= '';
1804 } //defaultDataElement