| [ Index ] |
|
Code source de Joomla 1.0.13 |
1 <?php 2 /** 3 * DOMIT! is a non-validating, but lightweight and fast DOM parser for PHP 4 * @package domit-xmlparser 5 * @subpackage domit-xmlparser-main 6 * @version 1.01 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 12 **/ 13 14 if (!defined('DOMIT_INCLUDE_PATH')) { 15 define('DOMIT_INCLUDE_PATH', (dirname(__FILE__) . "/")); 16 } 17 18 /** current version of DOMIT! */ 19 define ('DOMIT_VERSION', '1.01'); 20 21 /** XML namespace URI */ 22 define ('DOMIT_XML_NAMESPACE', 'http://www.w3.org/xml/1998/namespace'); 23 24 /** XMLNS namespace URI */ 25 define ('DOMIT_XMLNS_NAMESPACE', 'http://www.w3.org/2000/xmlns/'); 26 27 /** 28 * @global array Flipped version of $definedEntities array, to allow two-way conversion of entities 29 * 30 * Made global so that Attr nodes, which have no ownerDocument property, can access the array 31 */ 32 $GLOBALS['DOMIT_defined_entities_flip'] = array(); 33 34 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_shared.php'); 35 36 /** 37 * The base class of all DOMIT node types 38 * 39 * @package domit-xmlparser 40 * @subpackage domit-xmlparser-main 41 * @author John Heinstein <johnkarl@nbnet.nb.ca> 42 */ 43 class DOMIT_Node { 44 /** @var string The name of the node, varies according to node type */ 45 var $nodeName = null; 46 /** @var string The value of the node, varies according to node type */ 47 var $nodeValue = null; 48 /** @var int The type of node, e.g. CDataSection */ 49 var $nodeType = null; 50 /** @var Object A reference to the parent of the current node */ 51 var $parentNode = null; 52 /** @var Array An array of child node references */ 53 var $childNodes = null; 54 /** @var Object A reference to the first node in the childNodes list */ 55 var $firstChild = null; 56 /** @var Object A reference to the last node in the childNodes list */ 57 var $lastChild = null; 58 /** @var Object A reference to the node prior to the current node in its parents childNodes list */ 59 var $previousSibling = null; 60 /** @var Object A reference to the node after the current node in its parents childNodes list */ 61 var $nextSibling = null; 62 /** @var Object A NodeList of attribute nodes */ 63 var $attributes = null; 64 /** @var Object A reference to the Document node */ 65 var $ownerDocument = null; 66 /** @var String A URI that identifies the XML namespace to which the node belongs */ 67 var $namespaceURI = null; 68 /** @var String The namespace prefix for the node */ 69 var $prefix = null; 70 /** @var String The local name of the node */ 71 var $localName = null; 72 /** @var string The unique node id */ 73 var $uid; 74 /** @var int The number of children of the current node */ 75 var $childCount = 0; 76 77 /** 78 * Raises error if abstract class is directly instantiated 79 */ 80 function DOMIT_Node() { 81 DOMIT_DOMException::raiseException(DOMIT_ABSTRACT_CLASS_INSTANTIATION_ERR, 82 'Cannot instantiate abstract class DOMIT_Node'); 83 } //DOMIT_Node 84 85 /** 86 * DOMIT_Node constructor, assigns a uid 87 */ 88 function _constructor() { 89 global $uidFactory; 90 $this->uid = $uidFactory->generateUID(); 91 } //_constructor 92 93 /** 94 * Appends a node to the childNodes list of the current node 95 * @abstract 96 * @param Object The node to be appended 97 * @return Object The appended node 98 */ 99 function &appendChild(&$child) { 100 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 101 ('Method appendChild cannot be called by class ' . get_class($this))); 102 } //appendChild 103 104 /** 105 * Inserts a node to the childNodes list of the current node 106 * @abstract 107 * @param Object The node to be inserted 108 * @param Object The node before which the insertion is to occur 109 * @return Object The inserted node 110 */ 111 function &insertBefore(&$newChild, &$refChild) { 112 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 113 ('Method insertBefore cannot be called by class ' . get_class($this))); 114 } //insertBefore 115 116 /** 117 * Replaces a node with another 118 * @abstract 119 * @param Object The new node 120 * @param Object The old node 121 * @return Object The new node 122 */ 123 function &replaceChild(&$newChild, &$oldChild) { 124 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 125 ('Method replaceChild cannot be called by class ' . get_class($this))); 126 } //replaceChild 127 128 /** 129 * Removes a node from the childNodes list of the current node 130 * @abstract 131 * @param Object The node to be removed 132 * @return Object The removed node 133 */ 134 function &removeChild(&$oldChild) { 135 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 136 ('Method removeChild cannot be called by class ' . get_class($this))); 137 } //removeChild 138 139 /** 140 * Returns the index of the specified node in a childNodes list 141 * @param Array The childNodes array to be searched 142 * @param Object The node targeted by the search 143 * @return int The index of the target node, or -1 if not found 144 */ 145 function getChildNodeIndex(&$arr, &$child) { 146 $index = -1; 147 $total = count($arr); 148 149 for ($i = 0; $i < $total; $i++) { 150 if ($child->uid == $arr[$i]->uid) { 151 $index = $i; 152 break; 153 } 154 } 155 156 return $index; 157 } //getChildNodeIndex 158 159 /** 160 * Determines whether a node has any children 161 * @return boolean True if any child nodes are present 162 */ 163 function hasChildNodes() { 164 return ($this->childCount > 0); 165 } //hasChildNodes 166 167 /** 168 * Determines whether a node has any attributes 169 * @return boolean True if the node has attributes 170 */ 171 function hasAttributes() { 172 //overridden in DOMIT_Element 173 return false; 174 } //hasChildNodes 175 176 /** 177 * Collapses adjacent text nodes in entire node subtree 178 */ 179 function normalize() { 180 if (($this->nodeType == DOMIT_DOCUMENT_NODE) && ($this->documentElement != null)) { 181 $this->documentElement->normalize(); 182 } 183 } //normalize 184 185 /** 186 * Copies a node and/or its children 187 * @abstract 188 * @param boolean True if all child nodes are also to be cloned 189 * @return Object A copy of the node and/or its children 190 */ 191 function &cloneNode($deep = false) { 192 DOMIT_DOMException::raiseException(DOMIT_ABSTRACT_METHOD_INVOCATION_ERR, 193 'Cannot invoke abstract method DOMIT_Node->cloneNode($deep). Must provide an overridden method in your subclass.'); 194 } //cloneNode 195 196 /** 197 * Adds elements with the specified tag name to a NodeList collection 198 * @param Object The NodeList collection 199 * @param string The tag name of matching elements 200 */ 201 function getNamedElements(&$nodeList, $tagName) { 202 //Implemented in DOMIT_Element. 203 //Needs to be here though! This is called against all nodes in the document. 204 } //getNamedElements 205 206 /** 207 * Sets the ownerDocument property of a node to the containing DOMIT_Document 208 * @param Object A reference to the document element of the DOMIT_Document 209 */ 210 function setOwnerDocument(&$rootNode) { 211 if ($rootNode->ownerDocument == null) { 212 unset($this->ownerDocument); 213 $this->ownerDocument = null; 214 } 215 else { 216 $this->ownerDocument =& $rootNode->ownerDocument; 217 } 218 219 $total = $this->childCount; 220 221 for ($i = 0; $i < $total; $i++) { 222 $this->childNodes[$i]->setOwnerDocument($rootNode); 223 } 224 } //setOwnerDocument 225 226 /** 227 * Tests whether a value is null, and if so, returns a default value 228 * @param mixed The value to be tested 229 * @param mixed The default value 230 * @return mixed The specified value, or the default value if null 231 */ 232 function &nvl(&$value,$default) { 233 if (is_null($value)) return $default; 234 return $value; 235 } //nvl 236 237 /** 238 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like expression. 239 * @abstract 240 * @param string The query pattern 241 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node 242 * @return mixed A NodeList or single node that matches the pattern 243 */ 244 function &getElementsByPath($pattern, $nodeIndex = 0) { 245 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 246 ('Method getElementsByPath cannot be called by class ' . get_class($this))); 247 } //getElementsByPath 248 249 /** 250 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like attribute expression (NOT YET IMPLEMENTED!) 251 * @abstract 252 * @param string The query pattern 253 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node 254 * @return mixed A NodeList or single node that matches the pattern 255 */ 256 function &getElementsByAttributePath($pattern, $nodeIndex = 0) { 257 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 258 ('Method getElementsByAttributePath cannot be called by class ' . get_class($this))); 259 } //getElementsByAttributePath 260 261 /** 262 * Adds all child nodes of the specified nodeType to the NodeList 263 * @abstract 264 * @param Object The NodeList collection 265 * @param string The nodeType of matching nodes 266 */ 267 function getTypedNodes(&$nodeList, $type) { 268 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 269 ('Method getTypedNodes cannot be called by class ' . get_class($this))); 270 } //getTypedNodes 271 272 /** 273 * Adds all child nodes of the specified nodeValue to the NodeList 274 * @abstract 275 * @param Object The NodeList collection 276 * @param string The nodeValue of matching nodes 277 */ 278 function getValuedNodes(&$nodeList, $value) { 279 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 280 ('Method getValuedNodes cannot be called by class ' . get_class($this))); 281 } //getValuedNodes 282 283 /** 284 * Returns the concatented text of the current node and its children 285 * @return string The concatented text of the current node and its children 286 */ 287 function getText() { 288 return $this->nodeValue; 289 } //getText 290 291 /** 292 * Indicates whether the specified feature is supported by the DOM implementation and this node 293 * @param string The feature 294 * @param string The version of the DOM implementation 295 * @return boolean True if the specified feature is supported 296 */ 297 function isSupported($feature, $version = null) { 298 //don't worry about parsing based on version at this point in time; 299 //the only feature that is supported is 'XML'... 300 if (($version == '1.0') || ($version == '2.0') || ($version == null)) { 301 if (strtoupper($feature) == 'XML') { 302 return true; 303 } 304 } 305 306 return false; 307 } //isSupported 308 309 /** 310 * Formats a string for presentation as HTML 311 * @param string The string to be formatted 312 * @param boolean True if the string is to be sent directly to output 313 * @return string The HTML formatted string 314 */ 315 function forHTML($str, $doPrint = false) { 316 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_utilities.php'); 317 return DOMIT_Utilities::forHTML($str, $doPrint); 318 } //forHTML 319 320 /** 321 * Generates an array representation of the node and its children 322 * @abstract 323 * @return Array A representation of the node and its children 324 */ 325 function toArray() { 326 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 327 ('Method toArray cannot be called by class ' . get_class($this))); 328 } //toArray 329 330 /** 331 * A node event that can be set to fire upon document loading, used for node initialization 332 * @abstract 333 */ 334 function onLoad() { 335 //you can override this method if you subclass any of the 336 //DOMIT_Nodes. It's a way of performing 337 //initialization of your subclass as soon as the document 338 //has been loaded (as opposed to as soon as the current node 339 //has been instantiated). 340 } //onLoad 341 342 /** 343 * Clears previousSibling, nextSibling, and parentNode references from a node that has been removed 344 */ 345 function clearReferences() { 346 if ($this->previousSibling != null) { 347 unset($this->previousSibling); 348 $this->previousSibling = null; 349 } 350 if ($this->nextSibling != null) { 351 unset($this->nextSibling); 352 $this->nextSibling = null; 353 } 354 if ($this->parentNode != null) { 355 unset($this->parentNode); 356 $this->parentNode = null; 357 } 358 } //clearReferences 359 360 /** 361 * Removes the node from the document 362 */ 363 function delete () { 364 if ($this->parentNode != null) { 365 $this->parentNode->removeChild($node); 366 } 367 } //delete 368 369 /** 370 * Generates a normalized (formatted for readability) representation of the node and its children 371 * @param boolean True if HTML readable output is desired 372 * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities 373 * @return string The formatted string representation 374 */ 375 function toNormalizedString($htmlSafe = false, $subEntities = false) { 376 //require this file for generating a normalized (readable) xml string representation 377 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_utilities.php'); 378 global $DOMIT_defined_entities_flip; 379 380 $result = DOMIT_Utilities::toNormalizedString($this, $subEntities, $DOMIT_defined_entities_flip); 381 382 if ($htmlSafe) $result = $this->forHTML($result); 383 384 return $result; 385 } //toNormalizedString 386 } //DOMIT_Node 387 388 /** 389 * A parent class for nodes which possess child nodes 390 * 391 * @package domit-xmlparser 392 * @subpackage domit-xmlparser-main 393 * @author John Heinstein <johnkarl@nbnet.nb.ca> 394 */ 395 class DOMIT_ChildNodes_Interface extends DOMIT_Node { 396 /** 397 * Raises error if abstract class is directly instantiated 398 */ 399 function DOMIT_ChildNodes_Interface() { 400 DOMIT_DOMException::raiseException(DOMIT_ABSTRACT_CLASS_INSTANTIATION_ERR, 401 'Cannot instantiate abstract class DOMIT_ChildNodes_Interface'); 402 } //DOMIT_ChildNodes_Interface 403 404 /** 405 * Appends a node to the childNodes list of the current node 406 * @param Object The node to be appended 407 * @return Object The appended node 408 */ 409 function &appendChild(&$child) { 410 if ($child->nodeType == DOMIT_ATTRIBUTE_NODE) { 411 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 412 ('Cannot add a node of type ' . get_class($child) . ' using appendChild')); 413 } 414 else if ($child->nodeType == DOMIT_DOCUMENT_FRAGMENT_NODE) { 415 $total = $child->childCount; 416 417 for ($i = 0; $i < $total; $i++) { 418 $currChild =& $child->childNodes[$i]; 419 $this->appendChild($currChild); 420 } 421 } 422 else { 423 if (!($this->hasChildNodes())) { 424 $this->childNodes[0] =& $child; 425 $this->firstChild =& $child; 426 } 427 else { 428 //remove $child if it already exists 429 $index = $this->getChildNodeIndex($this->childNodes, $child); 430 431 if ($index != -1) { 432 $this->removeChild($child); 433 } 434 435 //append child 436 $numNodes = $this->childCount; 437 //BB: was bug auto-created wrong childnodes[-1]: added IF 438 if ($numNodes > 0) { 439 $prevSibling =& $this->childNodes[($numNodes - 1)]; 440 } 441 442 $this->childNodes[$numNodes] =& $child; 443 444 //set next and previous relationships 445 //BB: added this line and the else part to finish correcting bug 446 if (isset( $prevSibling )) { 447 $child->previousSibling =& $prevSibling; 448 $prevSibling->nextSibling =& $child; 449 } else { 450 unset( $child->previousSibling ); 451 $child->previousSibling = null; 452 $this->firstChild =& $child; 453 } 454 } 455 } 456 457 $this->lastChild =& $child; 458 $child->parentNode =& $this; 459 460 unset($child->nextSibling); 461 $child->nextSibling = null; 462 463 $child->setOwnerDocument($this); 464 $this->childCount++; 465 466 return $child; 467 468 } //appendChild 469 470 /** 471 * Inserts a node to the childNodes list of the current node 472 * @param Object The node to be inserted 473 * @param Object The node before which the insertion is to occur 474 * @return Object The inserted node 475 */ 476 function &insertBefore(&$newChild, &$refChild) { 477 if ($newChild->nodeType == DOMIT_ATTRIBUTE_NODE) { 478 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 479 ('Cannot add a node of type ' . get_class($newChild) . ' using insertBefore')); 480 } 481 482 if (($refChild->nodeType == DOMIT_DOCUMENT_NODE) || 483 //($refChild->parentNode->nodeType == DOMIT_DOCUMENT_NODE) || 484 ($refChild->parentNode == null)) { 485 486 DOMIT_DOMException::raiseException(DOMIT_NOT_FOUND_ERR, 487 'Reference child not present in the child nodes list.'); 488 } 489 490 //if reference child is also the node to be inserted 491 //leave the document as is and don't raise an exception 492 if ($refChild->uid == $newChild->uid) { 493 return $newChild; 494 } 495 496 //if $newChild is a DocumentFragment, 497 //loop through and insert each node separately 498 if ($newChild->nodeType == DOMIT_DOCUMENT_FRAGMENT_NODE) { 499 $total = $newChild->childCount; 500 501 for ($i = 0; $i < $total; $i++) { 502 $currChild =& $newChild->childNodes[$i]; 503 $this->insertBefore($currChild, $refChild); 504 } 505 506 return $newChild; 507 } 508 509 //remove $newChild if it already exists 510 $index = $this->getChildNodeIndex($this->childNodes, $newChild); 511 if ($index != -1) { 512 $this->removeChild($newChild); 513 } 514 515 //find index of $refChild in childNodes 516 $index = $this->getChildNodeIndex($this->childNodes, $refChild); 517 518 if ($index != -1) { 519 //reset sibling chain 520 if ($refChild->previousSibling != null) { 521 $refChild->previousSibling->nextSibling =& $newChild; 522 $newChild->previousSibling =& $refChild->previousSibling; 523 } 524 else { 525 $this->firstChild =& $newChild; 526 527 if ($newChild->previousSibling != null) { 528 unset($newChild->previousSibling); 529 $newChild->previousSibling = null; 530 } 531 } 532 533 $newChild->parentNode =& $refChild->parentNode; 534 $newChild->nextSibling =& $refChild; 535 $refChild->previousSibling =& $newChild; 536 537 //add node to childNodes 538 $i = $this->childCount; 539 540 while ($i >= 0) { 541 if ($i > $index) { 542 $this->childNodes[$i] =& $this->childNodes[($i - 1)]; 543 } 544 else if ($i == $index) { 545 $this->childNodes[$i] =& $newChild; 546 } 547 $i--; 548 } 549 550 $this->childCount++; 551 } 552 else { 553 $this->appendChild($newChild); 554 } 555 556 $newChild->setOwnerDocument($this); 557 return $newChild; 558 } //insertBefore 559 560 /** 561 * Replaces a node with another 562 * @param Object The new node 563 * @param Object The old node 564 * @return Object The new node 565 */ 566 function &replaceChild(&$newChild, &$oldChild) { 567 if ($newChild->nodeType == DOMIT_ATTRIBUTE_NODE) { 568 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 569 ('Cannot add a node of type ' . get_class($newChild) . ' using replaceChild')); 570 } 571 else if ($newChild->nodeType == DOMIT_DOCUMENT_FRAGMENT_NODE) { //if $newChild is a DocumentFragment 572 //replace the first node then loop through and insert each node separately 573 $total = $newChild->childCount; 574 575 if ($total > 0) { 576 $newRef =& $newChild->lastChild; 577 $this->replaceChild($newRef, $oldChild); 578 579 for ($i = 0; $i < ($total - 1); $i++) { 580 $currChild =& $newChild->childNodes[$i]; 581 $this->insertBefore($currChild, $newRef); 582 } 583 } 584 585 return $newChild; 586 } 587 else { 588 if ($this->hasChildNodes()) { 589 //remove $newChild if it already exists 590 $index = $this->getChildNodeIndex($this->childNodes, $newChild); 591 if ($index != -1) { 592 $this->removeChild($newChild); 593 } 594 595 //find index of $oldChild in childNodes 596 $index = $this->getChildNodeIndex($this->childNodes, $oldChild); 597 598 if ($index != -1) { 599 $newChild->ownerDocument =& $oldChild->ownerDocument; 600 $newChild->parentNode =& $oldChild->parentNode; 601 602 //reset sibling chain 603 if ($oldChild->previousSibling == null) { 604 unset($newChild->previousSibling); 605 $newChild->previousSibling = null; 606 } 607 else { 608 $oldChild->previousSibling->nextSibling =& $newChild; 609 $newChild->previousSibling =& $oldChild->previousSibling; 610 } 611 612 if ($oldChild->nextSibling == null) { 613 unset($newChild->nextSibling); 614 $newChild->nextSibling = null; 615 } 616 else { 617 $oldChild->nextSibling->previousSibling =& $newChild; 618 $newChild->nextSibling =& $oldChild->nextSibling; 619 } 620 621 $this->childNodes[$index] =& $newChild; 622 623 if ($index == 0) $this->firstChild =& $newChild; 624 if ($index == ($this->childCount - 1)) $this->lastChild =& $newChild; 625 626 $newChild->setOwnerDocument($this); 627 return $newChild; 628 } 629 } 630 631 DOMIT_DOMException::raiseException(DOMIT_NOT_FOUND_ERR, 632 ('Reference node for replaceChild not found.')); 633 } 634 } //replaceChild 635 636 /** 637 * Removes a node from the childNodes list of the current node 638 * @param Object The node to be removed 639 * @return Object The removed node 640 */ 641 function &removeChild(&$oldChild) { 642 if ($this->hasChildNodes()) { 643 //find index of $oldChild in childNodes 644 $index = $this->getChildNodeIndex($this->childNodes, $oldChild); 645 646 if ($index != -1) { 647 //reset sibling chain 648 if (($oldChild->previousSibling != null) && ($oldChild->nextSibling != null)) { 649 $oldChild->previousSibling->nextSibling =& $oldChild->nextSibling; 650 $oldChild->nextSibling->previousSibling =& $oldChild->previousSibling; 651 } 652 else if (($oldChild->previousSibling != null) && ($oldChild->nextSibling == null)) { 653 $this->lastChild =& $oldChild->previousSibling; 654 unset($oldChild->previousSibling->nextSibling); 655 $oldChild->previousSibling->nextSibling = null; 656 } 657 else if (($oldChild->previousSibling == null) && ($oldChild->nextSibling != null)) { 658 unset($oldChild->nextSibling->previousSibling); 659 $oldChild->nextSibling->previousSibling = null; 660 $this->firstChild =& $oldChild->nextSibling; 661 } 662 else if (($oldChild->previousSibling == null) && ($oldChild->nextSibling == null)) { 663 unset($this->firstChild); 664 $this->firstChild = null; 665 unset($this->lastChild); 666 $this->lastChild = null; 667 } 668 669 $total = $this->childCount; 670 671 //remove node from childNodes 672 for ($i = 0; $i < $total; $i++) { 673 if ($i == ($total - 1)) { 674 array_splice($this->childNodes, $i, 1); 675 } 676 else if ($i >= $index) { 677 $this->childNodes[$i] =& $this->childNodes[($i + 1)]; 678 } 679 } 680 681 $this->childCount--; 682 683 $oldChild->clearReferences(); 684 return $oldChild; 685 } 686 } 687 688 DOMIT_DOMException::raiseException(DOMIT_NOT_FOUND_ERR, 689 ('Target node for removeChild not found.')); 690 } //removeChild 691 692 693 /** 694 * Searches the element tree for an element with the specified attribute name and value. 695 * @param string The value of the attribute 696 * @param string The name of the attribute 697 * @param boolean True if the first found node is to be returned as a node instead of a nodelist 698 * @param boolean True if uid is to be considered an attribute 699 * @return object A NodeList of found elements, or null 700 */ 701 function &getElementsByAttribute($attrName = 'id', $attrValue = '', 702 $returnFirstFoundNode = false, $treatUIDAsAttribute = false) { 703 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_nodemaps.php'); 704 705 $nodelist = new DOMIT_NodeList(); 706 707 switch ($this->nodeType) { 708 case DOMIT_ELEMENT_NODE: 709 $this->_getElementsByAttribute($nodelist, $attrName, $attrValue, 710 $returnFirstFoundNode, $treatUIDAsAttribute); 711 break; 712 713 case DOMIT_DOCUMENT_NODE: 714 if ($this->documentElement != null) { 715 $this->documentElement->_getElementsByAttribute($nodelist, 716 $attrName, $attrValue, $returnFirstFoundNode, $treatUIDAsAttribute); 717 } 718 break; 719 } 720 721 if ($returnFirstFoundNode) { 722 if ($nodelist->getLength() > 0) { 723 return $nodelist->item(0); 724 } 725 else { 726 $null = null; 727 return $null; 728 } 729 } 730 else { 731 return $nodelist; 732 } 733 } //getElementsByAttribute 734 735 /** 736 * Searches the element tree for an element with the specified attribute name and value. 737 * @param object The node list of found elements 738 * @param string The value of the attribute 739 * @param string The name of the attribute 740 * @param boolean True if the first found node is to be returned as a node instead of a nodelist 741 * @param boolean True if uid is to be considered an attribute 742 * @param boolean True the node has been found 743 */ 744 function _getElementsByAttribute(&$nodelist, $attrName, $attrValue, 745 $returnFirstFoundNode, $treatUIDAsAttribute, $foundNode = false) { 746 if (!($foundNode && $returnFirstFoundNode)) { 747 if (($this->getAttribute($attrName) == $attrValue) || 748 ($treatUIDAsAttribute && ($attrName == 'uid') && ($this->uid == $attrValue))) { 749 $nodelist->appendNode($this); 750 $foundNode = true; 751 if ($returnFirstFoundNode) return; 752 } 753 754 $total = $this->childCount; 755 756 for ($i = 0; $i < $total; $i++) { 757 $currNode =& $this->childNodes[$i]; 758 759 if ($currNode->nodeType == DOMIT_ELEMENT_NODE) { 760 $currNode->_getElementsByAttribute($nodelist, 761 $attrName, $attrValue, $returnFirstFoundNode, 762 $treatUIDAsAttribute, $foundNode); 763 } 764 765 } 766 } 767 } //_getElementsByAttribute 768 769 /** 770 * Performs an XPath query 771 * @param string The query pattern 772 * @return Object A NodeList containing the found nodes 773 */ 774 function &selectNodes($pattern, $nodeIndex = 0) { 775 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_xpath.php'); 776 777 $xpParser = new DOMIT_XPath(); 778 779 return $xpParser->parsePattern($this, $pattern, $nodeIndex); 780 } //selectNodes 781 782 /** 783 * Converts the childNodes array into a NodeList object 784 * @return Object A NodeList containing elements of the childNodes array 785 */ 786 function &childNodesAsNodeList() { 787 require_once ('xml_domit_nodemaps.php'); 788 $myNodeList = new DOMIT_NodeList(); 789 790 $total = $this->childCount; 791 792 for ($i = 0; $i < $total; $i++) { 793 $myNodeList->appendNode($this->childNodes[$i]); 794 } 795 796 return $myNodeList; 797 } //childNodesAsNodeList 798 } //DOMIT_ChildNodes_Interface 799 800 /** 801 * A class representing the DOM Document 802 * 803 * @package domit-xmlparser 804 * @subpackage domit-xmlparser-main 805 * @author John Heinstein <johnkarl@nbnet.nb.ca> 806 */ 807 class DOMIT_Document extends DOMIT_ChildNodes_Interface { 808 /** @var Object The xml declaration processing instruction */ 809 var $xmlDeclaration; 810 /** @var Object A reference to a DOMIT_DocType object */ 811 var $doctype; 812 /** @var Object A reference to the root node of the DOM document */ 813 var $documentElement; 814 /** @var string The parser used to process the DOM document, either "EXPAT" or "SAXY" */ 815 var $parser; 816 /** @var Object A reference to the DOMIT_DOMImplementation object */ 817 var $implementation; 818 /** @var boolean True if the DOM document has been modifed since being parsed (NOT YET IMPLEMENTED!) */ 819 var $isModified; 820 /** @var boolean True if whitespace is to be preserved during parsing */ 821 var $preserveWhitespace = false; 822 /** @var Array User defined translation table for XML entities; passed to SAXY */ 823 var $definedEntities = array(); 824 /** @var boolean If true, loadXML or parseXML will attempt to detect and repair invalid xml */ 825 var $doResolveErrors = false; 826 /** @var boolean If true, elements tags will be rendered to string as <element></element> rather than <element/> */ 827 var $doExpandEmptyElementTags = false; 828 /** @var array A list of exceptions to the empty element expansion rule */ 829 var $expandEmptyElementExceptions = array(); 830 /** @var boolean If true, namespaces will be processed */ 831 var $isNamespaceAware = false; 832 /** @var int The error code returned by the SAX parser */ 833 var $errorCode = 0; 834 /** @var string The error string returned by the SAX parser */ 835 var $errorString = ''; 836 /** @var object A reference to a http connection or proxy server, if one is required */ 837 var $httpConnection = null; 838 /** @var boolean True if php_http_client_generic is to be used instead of PHP get_file_contents to retrieve xml data */ 839 var $doUseHTTPClient = false; 840 /** @var array An array of namespacesURIs mapped to prefixes */ 841 var $namespaceURIMap = array(); 842 843 /** 844 * DOM Document constructor 845 */ 846 function DOMIT_Document() { 847 $this->_constructor(); 848 $this->xmlDeclaration = null; 849 $this->doctype = null; 850 $this->documentElement = null; 851 $this->nodeType = DOMIT_DOCUMENT_NODE; 852 $this->nodeName = '#document'; 853 $this->ownerDocument =& $this; 854 $this->parser = ''; 855 $this->implementation = new DOMIT_DOMImplementation(); 856 } //DOMIT_Document 857 858 /** 859 * Specifies whether DOMIT! will try to fix invalid XML before parsing begins 860 * @param boolean True if errors are to be resolved 861 */ 862 function resolveErrors($truthVal) { 863 $this->doResolveErrors = $truthVal; 864 } //resolveErrors 865 866 /** 867 * Specifies whether DOMIT! processes namespace information 868 * @param boolean True if namespaces are to be processed 869 */ 870 function setNamespaceAwareness($truthVal) { 871 $this->isNamespaceAware = $truthVal; 872 } //setNamespaceAwareness 873 874 /** 875 * Specifies whether DOMIT! preserves whitespace when parsing 876 * @param boolean True if whitespace is to be preserved 877 */ 878 function preserveWhitespace($truthVal) { 879 $this->preserveWhitespace = $truthVal; 880 } //preserveWhitespace 881 882 /** 883 * Specifies the parameters of the http conection used to obtain the xml data 884 * @param string The ip address or domain name of the connection 885 * @param string The path of the connection 886 * @param int The port that the connection is listening on 887 * @param int The timeout value for the connection 888 * @param string The user name, if authentication is required 889 * @param string The password, if authentication is required 890 */ 891 function setConnection($host, $path = '/', $port = 80, $timeout = 0, $user = null, $password = null) { 892 require_once (DOMIT_INCLUDE_PATH . 'php_http_client_generic.php'); 893 894 $this->httpConnection = new php_http_client_generic($host, $path, $port, $timeout, $user, $password); 895 } //setConnection 896 897 /** 898 * Specifies basic authentication for an http connection 899 * @param string The user name 900 * @param string The password 901 */ 902 function setAuthorization($user, $password) { 903 $this->httpConnection->setAuthorization($user, $password); 904 } //setAuthorization 905 906 /** 907 * Specifies that a proxy is to be used to obtain the xml data 908 * @param string The ip address or domain name of the proxy 909 * @param string The path to the proxy 910 * @param int The port that the proxy is listening on 911 * @param int The timeout value for the connection 912 * @param string The user name, if authentication is required 913 * @param string The password, if authentication is required 914 */ 915 function setProxyConnection($host, $path = '/', $port = 80, $timeout = 0, $user = null, $password = null) { 916 require_once (DOMIT_INCLUDE_PATH . 'php_http_proxy.php'); 917 918 $this->httpConnection = new php_http_proxy($host, $path, $port, $timeout, $user, $password); 919 } //setProxyConnection 920 921 /** 922 * Specifies basic authentication for the proxy 923 * @param string The user name 924 * @param string The password 925 */ 926 function setProxyAuthorization($user, $password) { 927 $this->httpConnection->setProxyAuthorization($user, $password); 928 } //setProxyAuthorization 929 930 /** 931 * Specifies whether an HTTP client should be used to establish a connection 932 * @param boolean True if an HTTP client is to be used to establish the connection 933 */ 934 function useHTTPClient($truthVal) { 935 $this->doUseHTTPClient = $truthVal; 936 } //useHTTPClient 937 938 /** 939 * Returns the error code from the underlying SAX parser 940 * @return int The error code 941 */ 942 function getErrorCode() { 943 return $this->errorCode; 944 } //getErrorCode 945 946 /** 947 * Returns the error string from the underlying SAX parser 948 * @return string The error string 949 */ 950 function getErrorString() { 951 return $this->errorString; 952 } //getErrorString 953 954 /** 955 * Specifies whether elements tags will be rendered to string as <element></element> rather than <element/> 956 * @param boolean True if the expanded form is to be used 957 * @param mixed An array of tag names that should be excepted from expandEmptyElements rule (optional) 958 */ 959 function expandEmptyElementTags($truthVal, $expandEmptyElementExceptions = false) { 960 $this->doExpandEmptyElementTags = $truthVal; 961 962 if (is_array($expandEmptyElementExceptions)) { 963 $this->expandEmptyElementExceptions = $expandEmptyElementExceptions; 964 } 965 } //expandEmptyElementTags 966 967 /** 968 * Set the specified node as document element 969 * @param Object The node that is to become document element 970 * @return Object The new document element 971 */ 972 function &setDocumentElement(&$node) { 973 if ($node->nodeType == DOMIT_ELEMENT_NODE) { 974 if ($this->documentElement == null) { 975 parent::appendChild($node); 976 } 977 else { 978 parent::replaceChild($node, $this->documentElement); 979 } 980 981 $this->documentElement =& $node; 982 } 983 else { 984 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 985 ('Cannot add a node of type ' . get_class($node) . ' as a Document Element.')); 986 } 987 988 return $node; 989 } //setDocumentElement 990 991 /** 992 * Imports a node (and optionally its children) from another DOM Document 993 * @param object A reference to the node to be imported 994 * @param boolean True if the children of the imported node are also to be imported 995 * @return object The imported node (and, if specified, its children) 996 */ 997 function &importNode(&$importedNode, $deep = true) { 998 $parentNode = null; 999 return $this->_importNode($parentNode, $importedNode, $deep); 1000 } //importNode 1001 1002 1003 /** 1004 * Imports a node (and optionally its children) from another DOM Document 1005 * @param object A reference to the parent of the node to be imported 1006 * @param object A reference to the node to be imported 1007 * @param boolean True if the children of the imported node are also to be imported 1008 * @return object The imported node if it is the top level node, otherwise null 1009 */ 1010 function &_importNode(&$parentNode, &$sourceNode, $deep) { 1011 $hasChildren = false; 1012 1013 switch ($sourceNode->nodeType) { 1014 case DOMIT_ELEMENT_NODE: 1015 $hasChildren = true; 1016 1017 if ($this->isNamespaceAware) { 1018 $importedNode =& $this->createElementNS($sourceNode->namespaceURI, 1019 ($sourceNode->prefix . ":" . $sourceNode->localName)); 1020 } 1021 else { 1022 $importedNode =& $this->createElement($sourceNode->nodeName); 1023 } 1024 1025 $attrNodes =& $sourceNode->attributes; 1026 $total = $attrNodes->getLength(); 1027 1028 for ($i = 0; $i < $total; $i++) { 1029 $attrNode =& $attrNodes->item($i); 1030 1031 if ($this->isNamespaceAware) { 1032 $importedNode->setAttributeNS($attrNode->namespaceURI, 1033 ($attrNode->prefix . ":" . $attrNode->localName), $attrNode->nodeValue); 1034 } 1035 else { 1036 $importedNode->setAttribute($attrNode->nodeName, $attrNode->nodeValue); 1037 } 1038 } 1039 1040 break; 1041 1042 case DOMIT_ATTRIBUTE_NODE: 1043 if ($this->isNamespaceAware) { 1044 $importedNode =& $this->createAttributeNS($sourceNode->namespaceURI, 1045 ($sourceNode->prefix . ":" . $sourceNode->localName)); 1046 } 1047 else { 1048 $importedNode =& $this->createAttribute($sourceNode->nodeValue); 1049 } 1050 break; 1051 1052 case DOMIT_TEXT_NODE: 1053 $importedNode =& $this->createTextNode($sourceNode->nodeValue); 1054 break; 1055 1056 case DOMIT_CDATA_SECTION_NODE: 1057 $importedNode =& $this->createCDATASection($sourceNode->nodeValue); 1058 break; 1059 1060 case DOMIT_COMMENT_NODE: 1061 $importedNode =& $this->createComment($sourceNode->nodeValue); 1062 break; 1063 1064 case DOMIT_DOCUMENT_FRAGMENT_NODE: 1065 $hasChildren = true; 1066 $importedNode =& $this->createDocumentFragment(); 1067 break; 1068 1069 case DOMIT_PROCESSING_INSTRUCTION_NODE: 1070 $importedNode =& $this->createProcessingInstruction($sourceNode->nodeName, 1071 $sourceNode->nodeValue); 1072 break; 1073 1074 case DOMIT_DOCUMENT_NODE: 1075 case DOMIT_DOCUMENT_TYPE_NODE: 1076 DOMIT_DOMException::raiseException(DOMIT_NOT_SUPPORTED_ERR, 1077 ('Method importNode cannot be called by class ' . get_class($this))); 1078 break; 1079 } 1080 1081 if ($hasChildren && $deep) { 1082 $total = $sourceNode->childCount; 1083 1084 for ($i = 0; $i < $total; $i++) { 1085 $importedNode->appendChild( 1086 $this->_importNode($importedNode, $sourceNode->childNodes[$i], $deep)); 1087 } 1088 } 1089 1090 return $importedNode; 1091 } //_importNode 1092 1093 /** 1094 * Appends a node to the childNodes list of the current node 1095 * @param Object The node to be appended 1096 * @return Object The appended node 1097 */ 1098 function &appendChild(&$node) { 1099 switch ($node->nodeType) { 1100 case DOMIT_ELEMENT_NODE: 1101 if ($this->documentElement == null) { 1102 parent::appendChild($node); 1103 $this->setDocumentElement($node); 1104 } 1105 else { 1106 //error thrown if documentElement already exists! 1107 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1108 ('Cannot have more than one root node (documentElement) in a DOMIT_Document.')); 1109 } 1110 break; 1111 1112 case DOMIT_PROCESSING_INSTRUCTION_NODE: 1113 case DOMIT_COMMENT_NODE: 1114 parent::appendChild($node); 1115 break; 1116 1117 case DOMIT_DOCUMENT_TYPE_NODE: 1118 if ($this->doctype == null) { 1119 parent::appendChild($node); 1120 } 1121 else { 1122 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1123 ('Cannot have more than one doctype node in a DOMIT_Document.')); 1124 } 1125 break; 1126 1127 case DOMIT_DOCUMENT_FRAGMENT_NODE: 1128 $total = $node->childCount; 1129 1130 for ($i = 0; $i < $total; $i++) { 1131 $currChild =& $node->childNodes[$i]; 1132 $this->appendChild($currChild); 1133 } 1134 break; 1135 1136 default: 1137 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1138 ('Cannot add a node of type ' . get_class($node) . ' to a DOMIT_Document.')); 1139 } 1140 1141 return $node; 1142 } //appendChild 1143 1144 /** 1145 * Replaces a node with another 1146 * @param Object The new node 1147 * @param Object The old node 1148 * @return Object The new node 1149 */ 1150 function &replaceChild(&$newChild, &$oldChild) { 1151 if ($this->nodeType == DOMIT_DOCUMENT_FRAGMENT_NODE) { 1152 $total = $newChild->childCount; 1153 1154 if ($total > 0) { 1155 $newRef =& $newChild->lastChild; 1156 $this->replaceChild($newRef, $oldChild); 1157 1158 for ($i = 0; $i < ($total - 1); $i++) { 1159 $currChild =& $newChild->childNodes[$i]; 1160 parent::insertBefore($currChild, $newRef); 1161 } 1162 } 1163 } 1164 else { 1165 if (($this->documentElement != null) && ($oldChild->uid == $this->documentElement->uid)) { 1166 if ($newChild->nodeType == DOMIT_ELEMENT_NODE) { 1167 //replace documentElement with new node 1168 $this->setDocumentElement($newChild); 1169 } 1170 else { 1171 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1172 ('Cannot replace Document Element with a node of class ' . get_class($newChild))); 1173 } 1174 } 1175 else { 1176 switch ($newChild->nodeType) { 1177 case DOMIT_ELEMENT_NODE: 1178 if ($this->documentElement != null) { 1179 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1180 ('Cannot have more than one root node (documentElement) in a DOMIT_Document.')); 1181 } 1182 else { 1183 parent::replaceChild($newChild, $oldChild); 1184 } 1185 break; 1186 1187 case DOMIT_PROCESSING_INSTRUCTION_NODE: 1188 case DOMIT_COMMENT_NODE: 1189 parent::replaceChild($newChild, $oldChild); 1190 break; 1191 1192 case DOMIT_DOCUMENT_TYPE_NODE: 1193 if ($this->doctype != null) { 1194 if ($this->doctype->uid == $oldChild->uid) { 1195 parent::replaceChild($newChild, $oldChild); 1196 } 1197 else { 1198 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1199 ('Cannot have more than one doctype node in a DOMIT_Document.')); 1200 } 1201 } 1202 else { 1203 parent::replaceChild($newChild, $oldChild); 1204 } 1205 break; 1206 1207 default: 1208 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1209 ('Nodes of class ' . get_class($newChild) . ' cannot be children of a DOMIT_Document.')); 1210 } 1211 } 1212 } 1213 1214 return $newChild; 1215 } //replaceChild 1216 1217 /** 1218 * Inserts a node to the childNodes list of the current node 1219 * @param Object The node to be inserted 1220 * @param Object The node before which the insertion is to occur 1221 * @return Object The inserted node 1222 */ 1223 function &insertBefore(&$newChild, &$refChild) { 1224 $type = $newChild->nodeType; 1225 1226 if ($this->nodeType == DOMIT_DOCUMENT_FRAGMENT_NODE) { 1227 $total = $newChild->childCount; 1228 1229 for ($i = 0; $i < $total; $i++) { 1230 $currChild =& $newChild->childNodes[$i]; 1231 $this->insertBefore($currChild, $refChild); 1232 } 1233 } 1234 else if ($type == DOMIT_ELEMENT_NODE) { 1235 if ($this->documentElement == null) { 1236 parent::insertBefore($newChild, $refChild); 1237 $this->setDocumentElement($newChild); 1238 } 1239 else { 1240 //error thrown if documentElement already exists! 1241 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1242 ('Cannot have more than one root node (documentElement) in a DOMIT_Document.')); 1243 } 1244 } 1245 else if ($type == DOMIT_PROCESSING_INSTRUCTION_NODE) { 1246 parent::insertBefore($newChild, $refChild); 1247 } 1248 else if ($type == DOMIT_DOCUMENT_TYPE_NODE) { 1249 if ($this->doctype == null) { 1250 parent::insertBefore($newChild, $refChild); 1251 } 1252 else { 1253 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1254 ('Cannot have more than one doctype node in a DOMIT_Document.')); 1255 } 1256 } 1257 else { 1258 DOMIT_DOMException::raiseException(DOMIT_HIERARCHY_REQUEST_ERR, 1259 ('Cannot insert a node of type ' . get_class($newChild) . ' to a DOMIT_Document.')); 1260 } 1261 1262 return $newChild; 1263 } //insertBefore 1264 1265 /** 1266 * Removes a node from the childNodes list of the current node 1267 * @param Object The node to be removed 1268 * @return Object The removed node 1269 */ 1270 function &removeChild(&$oldChild) { 1271 if ($this->nodeType == DOMIT_DOCUMENT_FRAGMENT_NODE) { 1272 $total = $oldChild->childCount; 1273 1274 for ($i = 0; $i < $total; $i++) { 1275 $currChild =& $oldChild->childNodes[$i]; 1276 $this->removeChild($currChild); 1277 } 1278 } 1279 else { 1280 if (($this->documentElement != null) && ($oldChild->uid == $this->documentElement->uid)) { 1281 parent::removeChild($oldChild); 1282 $this->documentElement = null; 1283 } 1284 else { 1285 parent::removeChild($oldChild); 1286 } 1287 } 1288 1289 $oldChild->clearReferences(); 1290 return $oldChild; 1291 } //removeChild 1292 1293 1294 /** 1295 * Creates a new DOMIT_DocumentFragment node 1296 * @return Object The new document fragment node 1297 */ 1298 function &createDocumentFragment() { 1299 $node = new DOMIT_DocumentFragment(); 1300 $node->ownerDocument =& $this; 1301 1302 return $node; 1303 } //createDocumentFragment 1304 1305 /** 1306 * Creates a new DOMIT_Attr node 1307 * @param string The name of the attribute 1308 * @return Object The new attribute node 1309 */ 1310 function &createAttribute($name) { 1311 $node = new DOMIT_Attr($name); 1312 1313 return $node; 1314 } //createAttribute 1315 1316 /** 1317 * Creates a new DOMIT_Attr node (namespace aware) 1318 * @param string The namespaceURI of the attribute 1319 * @param string The qualifiedName of the attribute 1320 * @return Object The new attribute node 1321 */ 1322 function &createAttributeNS($namespaceURI, $qualifiedName) { 1323 $node = new DOMIT_Attr($qualifiedName); 1324 $node->namespaceURI = $namespaceURI; 1325 1326 $colonIndex = strpos($qualifiedName, ":"); 1327 1328 if ($colonIndex !== false) { 1329 $node->prefix = substr($qualifiedName, 0, $colonIndex); 1330 $node->localName = substr($qualifiedName, ($colonIndex + 1)); 1331 } 1332 else { 1333 $node->prefix = ''; 1334 $node->localName = $qualifiedName; 1335 } 1336 1337 return $node; 1338 } //createAttributeNS 1339 1340 /** 1341 * Creates a new DOMIT_Element node 1342 * @param string The tag name of the element 1343 * @return Object The new element 1344 */ 1345 function &createElement($tagName) { 1346 $node = new DOMIT_Element($tagName); 1347 $node->ownerDocument =& $this; 1348 1349 return $node; 1350 } //createElement 1351 1352 /** 1353 * Creates a new DOMIT_Element node (namespace aware) 1354 * @param string The namespaceURI of the element 1355 * @param string The qualifiedName of the element 1356 * @return Object The new element 1357 */ 1358 function &createElementNS($namespaceURI, $qualifiedName) { 1359 $node = new DOMIT_Element($qualifiedName); 1360 1361 $colonIndex = strpos($qualifiedName, ":"); 1362 1363 if ($colonIndex !== false) { 1364 $node->prefix = substr($qualifiedName, 0, $colonIndex); 1365 $node->localName = substr($qualifiedName, ($colonIndex + 1)); 1366 } 1367 else { 1368 $node->prefix = ''; 1369 $node->localName = $qualifiedName; 1370 } 1371 1372 $node->namespaceURI = $namespaceURI; 1373 1374 $node->ownerDocument =& $this; 1375 1376 return $node; 1377 } //createElementNS 1378 1379 /** 1380 * Creates a new DOMIT_Text node 1381 * @param string The text of the node 1382 * @return Object The new text node 1383 */ 1384 function &createTextNode($data) { 1385 $node = new DOMIT_TextNode($data); 1386 $node->ownerDocument =& $this; 1387 1388 return $node; 1389 } //createTextNode 1390 1391 /** 1392 * Creates a new DOMIT_CDataSection node 1393 * @param string The text of the CDATASection 1394 * @return Object The new CDATASection node 1395 */ 1396 function &createCDATASection($data) { 1397 $node = new DOMIT_CDATASection($data); 1398 $node->ownerDocument =& $this; 1399 1400 return $node; 1401 } //createCDATASection 1402 1403 /** 1404 * Creates a new DOMIT_Comment node 1405 * @param string The comment text 1406 * @return Object The new comment node 1407 */ 1408 function &createComment($text) { 1409 $node = new DOMIT_Comment($text); 1410 $node->ownerDocument =& $this; 1411 1412 return $node; 1413 } //createComment 1414 1415 /** 1416 * Creates a new DOMIT_ProcessingInstruction node 1417 * @param string The target of the processing instruction 1418 * @param string The data of the processing instruction 1419 * @return Object The new processing instruction node 1420 */ 1421 function &createProcessingInstruction($target, $data) { 1422 $node = new DOMIT_ProcessingInstruction($target, $data); 1423 $node->ownerDocument =& $this; 1424 1425 return $node; 1426 } //createProcessingInstruction 1427 1428 /** 1429 * Retrieves a NodeList of child elements with the specified tag name 1430 * @param string The matching element tag name 1431 * @return Object A NodeList of found elements 1432 */ 1433 function &getElementsByTagName($tagName) { 1434 $nodeList = new DOMIT_NodeList(); 1435 1436 if ($this->documentElement != null) { 1437 $this->documentElement->getNamedElements($nodeList, $tagName); 1438 } 1439 1440 return $nodeList; 1441 } //getElementsByTagName 1442 1443 /** 1444 * Retrieves a NodeList of child elements with the specified namespaceURI and localName 1445 * @param string The matching namespaceURI 1446 * @param string The matching localName 1447 * @return Object A NodeList of found elements 1448 */ 1449 function &getElementsByTagNameNS($namespaceURI, $localName) { 1450 $nodeList = new DOMIT_NodeList(); 1451 1452 if ($this->documentElement != null) { 1453 $this->documentElement->getNamedElementsNS($nodeList, $namespaceURI, $localName); 1454 } 1455 1456 return $nodeList; 1457 } //getElementsByTagNameNS 1458 1459 /** 1460 * Returns the element whose ID is given by elementId. 1461 * @param string The id of the matching element 1462 * @param boolean True if XML spec is to be strictly adhered to (only attributes xml:id are considered valid) 1463 * @return Object The found element or null 1464 */ 1465 function &getElementByID($elementID, $isStrict = true) { 1466 if ($this->isNamespaceAware) { 1467 if ($this->documentElement != null) { 1468 $targetAttrNode =& $this->documentElement->_getElementByID($elementID, $isStrict); 1469 return $targetAttrNode->ownerElement; 1470 } 1471 1472 $null = null; 1473 return $null; 1474 } 1475 else { 1476 DOMIT_DOMException::raiseException(DOMIT_INVALID_ACCESS_ERR, 1477 'Namespace awareness must be enabled to use method getElementByID'); 1478 } 1479 } //getElementByID 1480 1481 /** 1482 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like expression. 1483 * @param string The query pattern 1484 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node 1485 * @return mixed A NodeList or single node that matches the pattern 1486 */ 1487 function &getElementsByPath($pattern, $nodeIndex = 0) { 1488 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_getelementsbypath.php'); 1489 1490 $gebp = new DOMIT_GetElementsByPath(); 1491 $myResponse =& $gebp->parsePattern($this, $pattern, $nodeIndex); 1492 1493 return $myResponse; 1494 } //getElementsByPath 1495 1496 /** 1497 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like attribute expression (NOT YET IMPLEMENTED!) 1498 * @param string The query pattern 1499 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node 1500 * @return mixed A NodeList or single node that matches the pattern 1501 */ 1502 function &getElementsByAttributePath($pattern, $nodeIndex = 0) { 1503 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_getelementsbypath.php'); 1504 1505 $gabp = new DOMIT_GetElementsByAttributePath(); 1506 $myResponse =& $gabp->parsePattern($this, $pattern, $nodeIndex); 1507 1508 return $myResponse; 1509 } //getElementsByAttributePath 1510 1511 /** 1512 * Retrieves all child nodes of the specified nodeType 1513 * @param string The nodeType of matching nodes 1514 * @param Object The root node of the search 1515 * @return Object A NodeList containing found nodes 1516 */ 1517 function &getNodesByNodeType($type, &$contextNode) { 1518 $nodeList = new DOMIT_NodeList(); 1519 1520 if (($type == DOMIT_DOCUMENT_NODE) || ($contextNode->nodeType == DOMIT_DOCUMENT_NODE)){ 1521 $nodeList->appendNode($this); 1522 } 1523 else if ($contextNode->nodeType == DOMIT_ELEMENT_NODE) { 1524 $contextNode->getTypedNodes($nodeList, $type); 1525 } 1526 else if ($contextNode->uid == $this->uid) { 1527 if ($this->documentElement != null) { 1528 if ($type == DOMIT_ELEMENT_NODE) { 1529 $nodeList->appendNode($this->documentElement); 1530 } 1531 1532 $this->documentElement->getTypedNodes($nodeList, $type); 1533 } 1534 } 1535 1536 return $nodeList; 1537 } //getNodesByNodeType 1538 1539 /** 1540 * Retrieves all child nodes of the specified nodeValue 1541 * @param string The nodeValue of matching nodes 1542 * @param Object The root node of the search 1543 * @return Object A NodeList containing found nodes 1544 */ 1545 function &getNodesByNodeValue($value, &$contextNode) { 1546 $nodeList = new DOMIT_NodeList(); 1547 1548 if ($contextNode->uid == $this->uid) { 1549 if ($this->nodeValue == $value) { 1550 $nodeList->appendNode($this); 1551 } 1552 } 1553 1554 if ($this->documentElement != null) { 1555 $this->documentElement->getValuedNodes($nodeList, $value); 1556 } 1557 1558 return $nodeList; 1559 } //getNodesByNodeValue 1560 1561 /** 1562 * Parses an xml string 1563 * @param string The xml text to be parsed 1564 * @param boolean True if SAXY is to be used instead of Expat 1565 * @param boolean False if CDATA Section are to be generated as Text nodes 1566 * @param boolean True if onLoad is to be called on each node after parsing 1567 * @return boolean True if parsing is successful 1568 */ 1569 function parseXML($xmlText, $useSAXY = true, $preserveCDATA = true, $fireLoadEvent = false) { 1570 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_utilities.php'); 1571 1572 if ($this->doResolveErrors) { 1573 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_doctor.php'); 1574 $xmlText = DOMIT_Doctor::fixAmpersands($xmlText); 1575 } 1576 1577 if (DOMIT_Utilities::validateXML($xmlText)) { 1578 $domParser = new DOMIT_Parser(); 1579 1580 if ($useSAXY || (!function_exists('xml_parser_create'))) { 1581 //use SAXY parser to populate xml tree 1582 $this->parser = 'SAXY'; 1583 $success = $domParser->parseSAXY($this, $xmlText, $preserveCDATA, $this->definedEntities); 1584 } 1585 else { 1586 //use Expat parser to populate xml tree 1587 $this->parser = 'EXPAT'; 1588 $success = $domParser->parse($this, $xmlText, $preserveCDATA); 1589 } 1590 1591 if ($fireLoadEvent && ($this->documentElement != null)) $this->load($this->documentElement); 1592 1593 return $success; 1594 } 1595 else { 1596 return false; 1597 } 1598 } //parseXML 1599 1600 /** 1601 * Parses an xml file 1602 * @param string The xml file to be parsed 1603 * @param boolean True if SAXY is to be used instead of Expat 1604 * @param boolean False if CDATA Section are to be generated as Text nodes 1605 * @param boolean True if onLoad is to be called on each node after parsing 1606 * @return boolean True if parsing is successful 1607 */ 1608 function loadXML($filename, $useSAXY = true, $preserveCDATA = true, $fireLoadEvent = false) { 1609 $xmlText = $this->getTextFromFile($filename); 1610 1611 return $this->parseXML($xmlText, $useSAXY, $preserveCDATA, $fireLoadEvent); 1612 } //loadXML 1613 1614 /** 1615 * Establishes a connection, given an url 1616 * @param string The url of the data 1617 */ 1618 function establishConnection($url) { 1619 require_once (DOMIT_INCLUDE_PATH . 'php_http_client_generic.php'); 1620 1621 $host = php_http_connection::formatHost($url); 1622 $host = substr($host, 0, strpos($host, '/')); 1623 1624 $this->setConnection($host); 1625 } //establishConnection 1626 1627 /** 1628 * Retrieves text from a file 1629 * @param string The file path 1630 * @return string The text contained in the file 1631 */ 1632 function getTextFromFile($filename) { 1633 if ($this->doUseHTTPClient && (substr($filename, 0, 5) == 'http:')) { 1634 $this->establishConnection($filename); 1635 } 1636 1637 if ($this->httpConnection != null) { 1638 $response =& $this->httpConnection->get($filename); 1639 1640 $this->httpConnection->disconnect(); 1641 return $response->getResponse(); 1642 } 1643 else if (function_exists('file_get_contents')) { 1644 //if (file_exists($filename)) { 1645 return file_get_contents($filename); 1646 //} 1647 } 1648 else { 1649 require_once (DOMIT_INCLUDE_PATH . 'php_file_utilities.php'); 1650 1651 $fileContents =& php_file_utilities::getDataFromFile($filename, 'r'); 1652 return $fileContents; 1653 } 1654 1655 return ''; 1656 } //getTextFromFile 1657 1658 /** 1659 * Saves the current DOM document as an xml file 1660 * @param string The path of the xml file 1661 * @param boolean True if xml text is to be normalized before saving 1662 * @return boolean True if save is successful 1663 */ 1664 function saveXML($filename, $normalized = false) { 1665 if ($normalized) { 1666 $stringRep = $this->toNormalizedString(false, true); 1667 } 1668 else { 1669 $stringRep = $this->toString(false, true); 1670 } 1671 1672 return $this->saveTextToFile($filename, $stringRep); 1673 } //saveXML 1674 1675 /** 1676 * Saves text to a file 1677 * @param string The file path 1678 * @param string The text to be saved 1679 * @return boolean True if the save is successful 1680 */ 1681 function saveTextToFile($filename, $text) { 1682 if (function_exists('file_put_contents')) { 1683 file_put_contents($filename, $text); 1684 } 1685 else { 1686 require_once (DOMIT_INCLUDE_PATH . 'php_file_utilities.php'); 1687 php_file_utilities::putDataToFile($filename, $text, 'w'); 1688 } 1689 1690 return (file_exists($filename) && is_writable($filename)); 1691 } //saveTextToFile 1692 1693 /** 1694 * Indicates the SAX parser used to parse the current document 1695 * @return string Either "SAXY" or "EXPAT" 1696 */ 1697 function parsedBy() { 1698 return $this->parser; 1699 } //parsedBy 1700 1701 /** 1702 * Returns the concatented text of the current node and its children 1703 * @return string The concatented text of the current node and its children 1704 */ 1705 function getText() { 1706 if ($this->documentElement != null) { 1707 $root =& $this->documentElement; 1708 return $root->getText(); 1709 } 1710 1711 return ''; 1712 } //getText 1713 1714 /** 1715 * Returns a doctype object 1716 * @return mixed The doctype object, or null if none exists 1717 */ 1718 function getDocType() { 1719 return $this->doctype; 1720 } //getDocType 1721 1722 /** 1723 * Returns the xml declaration processing instruction 1724 * @return mixed The xml declaration processing instruction, or null if none exists 1725 */ 1726 function getXMLDeclaration() { 1727 return $this->xmlDeclaration; 1728 } //getXMLDeclaration 1729 1730 /** 1731 * Returns a reference to the DOMIT_DOMImplementation object 1732 * @return Object A reference to the DOMIT_DOMImplementation object 1733 */ 1734 function &getDOMImplementation() { 1735 return $this->implementation; 1736 } //getDOMImplementation 1737 1738 /** 1739 * Manages the firing of the onLoad() event 1740 * @param Object The parent node of the current recursion 1741 */ 1742 function load(&$contextNode) { 1743 $total = $contextNode->childCount; 1744 1745 for ($i = 0; $i < $total; $i++) { 1746 $currNode =& $contextNode->childNodes[$i]; 1747 $currNode->ownerDocument->load($currNode); 1748 } 1749 1750 $contextNode->onLoad(); 1751 } //load 1752 1753 /** 1754 * Returns the current version of DOMIT! 1755 * @return Object The current version of DOMIT! 1756 */ 1757 function getVersion() { 1758 return DOMIT_VERSION; 1759 } //getVersion 1760 1761 /** 1762 * Appends an array of entity mappings to the existing translation table 1763 * 1764 * Intended mainly to facilitate the conversion of non-ASCII entities into equivalent characters 1765 * 1766 * @param array A list of entity mappings in the format: array('&' => '&'); 1767 */ 1768 function appendEntityTranslationTable($table) { 1769 $this->definedEntities = $table; 1770 1771 global $DOMIT_defined_entities_flip; 1772 $DOMIT_defined_entities_flip = array_flip($table); 1773 } //appendEntityTranslationTable 1774 1775 /** 1776 * Generates an array representation of the node and its children 1777 * @return Array A representation of the node and its children 1778 */ 1779 function toArray() { 1780 $arReturn = array($this->nodeName => array()); 1781 $total = $this->childCount; 1782 1783 for ($i = 0; $i < $total; $i++) { 1784 $arReturn[$this->nodeName][$i] = $this->childNodes[$i]->toArray(); 1785 } 1786 1787 return $arReturn; 1788 } //toArray 1789 1790 /** 1791 * Copies a node and/or its children 1792 * @param boolean True if all child nodes are also to be cloned 1793 * @return Object A copy of the node and/or its children 1794 */ 1795 function &cloneNode($deep = false) { 1796 $className = get_class($this); 1797 $clone = new $className($this->nodeName); 1798 1799 if ($deep) { 1800 $total = $this->childCount; 1801 1802 for ($i = 0; $i < $total; $i++) { 1803 $currentChild =& $this->childNodes[$i]; 1804 $clone->appendChild($currentChild->cloneNode($deep)); 1805 1806 if ($currentChild->nodeType == DOMIT_DOCUMENT_TYPE_NODE) { 1807 $clone->doctype =& $clone->childNodes[$i]; 1808 } 1809 1810 if (($currentChild->nodeType == DOMIT_PROCESSING_INSTRUCTION_NODE) && 1811 ($currentChild->getTarget() == 'xml')) { 1812 $clone->xmlDeclaration =& $clone->childNodes[$i]; 1813 } 1814 } 1815 } 1816 1817 return $clone; 1818 } //cloneNode 1819 1820 /** 1821 * Generates a string representation of the node and its children 1822 * @param boolean True if HTML readable output is desired 1823 * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities 1824 * @return string The string representation 1825 */ 1826 function toString($htmlSafe = false, $subEntities = false) { 1827 $result = ''; 1828 $total = $this->childCount; 1829 1830 for ($i = 0; $i < $total; $i++) { 1831 $result .= $this->childNodes[$i]->toString(false, $subEntities); 1832 } 1833 1834 if ($htmlSafe) $result = $this->forHTML($result); 1835 1836 return $result; 1837 } //toString 1838 } //DOMIT_Document 1839 1840 /** 1841 * A class representing the DOM Element 1842 * 1843 * @package domit-xmlparser 1844 * @subpackage domit-xmlparser-main 1845 * @author John Heinstein <johnkarl@nbnet.nb.ca> 1846 */ 1847 class DOMIT_Element extends DOMIT_ChildNodes_Interface { 1848 /** @var array An array of namespacesURIs mapped to prefixes */ 1849 var $namespaceURIMap = array(); 1850 1851 /** 1852 * DOM Element constructor 1853 * @param string The tag name of the element 1854 */ 1855 function DOMIT_Element($tagName) { 1856 $this->_constructor(); 1857 $this->nodeType = DOMIT_ELEMENT_NODE; 1858 $this->nodeName = $tagName; 1859 $this->attributes = new DOMIT_NamedNodeMap_Attr(); 1860 $this->childNodes = array(); 1861 } //DOMIT_Element 1862 1863 /** 1864 * Returns the tag name of the element 1865 * @return string The tag name of the element 1866 */ 1867 function getTagName() { 1868 return $this->nodeName; 1869 } //getTagName 1870 1871 /** 1872 * Adds elements with the specified tag name to a NodeList collection 1873 * @param Object The NodeList collection 1874 * @param string The tag name of matching elements 1875 */ 1876 function getNamedElements(&$nodeList, $tagName) { 1877 if (($this->nodeName == $tagName) || ($tagName == '*')) { 1878 $nodeList->appendNode($this); 1879 } 1880 1881 $total = $this->childCount; 1882 1883 for ($i = 0; $i < $total; $i++) { 1884 $this->childNodes[$i]->getNamedElements($nodeList, $tagName); 1885 } 1886 } //getNamedElements 1887 1888 /** 1889 * Creates an xmlns declaration at the current element 1890 * @param array An array of namespace declarations in the scope of the current element 1891 */ 1892 function declareNamespace($localname, $value) { 1893 //namespace URI for xmlns attribute is: http://www.w3.org/2000/xmlns/ 1894 $this->setAttributeNS(DOMIT_XMLNS_NAMESPACE, ('xmlns:' . $localname), $value); 1895 1896 //add to local namespaceURI map 1897 $this->namespaceURIMap[$value] = $localname; 1898 } //declareNamespace 1899 1900 /** 1901 * Creates a default xmlns declaration at the current element 1902 * @param array An array of namespace declarations in the scope of the current element 1903 */ 1904 function declareDefaultNamespace($value) { 1905 //namespace URI for xmlns attribute is: http://www.w3.org/2000/xmlns/ 1906 $this->setAttributeNS(DOMIT_XMLNS_NAMESPACE, 'xmlns', $value); 1907 1908 //add to local namespaceURI map 1909 $this->namespaceURIMap[$value] = 'xmlns'; 1910 } //declareDefaultNamespace 1911 1912 /** 1913 * Returns an array of namespace declarations in the scope of the current element 1914 * @return array An array of namespace declarations in the scope of the current element 1915 */ 1916 function &getNamespaceDeclarationsInScope() { 1917 $nsMap = array(); 1918 1919 return $this->_getNameSpaceDeclarationsInScope($nsMap); 1920 } //getNamespacesInScope 1921 1922 /** 1923 * Returns an array of namespace declarations in the scope of the current element 1924 * @return array An array of namespace declarations in the scope of the current element 1925 */ 1926 function &_getNamespaceDeclarationsInScope(&$nsMap) { 1927 //grab local xmlns declarations if not already present 1928 foreach ($this->namespaceURIMap as $key => $value) { 1929 if (!isset($nsMap[$key])) { 1930 $nsMap[$key] = $value; 1931 } 1932 } 1933 1934 //move up the tree if not already at the top 1935 if ($this->parentNode->uid != $this->ownerDocument->uid) { 1936 $this->parentNode->_getNamespaceDeclarationsInScope($nsMap); 1937 } 1938 1939 return $nsMap; 1940 } //_getNamespacesInScope 1941 1942 /** 1943 * Returns the default xmlns declaration for the current element 1944 * @return string The default xmlns declaration for the current element 1945 */ 1946 function getDefaultNamespaceDeclaration() { 1947 if (in_array('xmlns', $this->namespaceURIMap)) { 1948 foreach ($this->namespaceURIMap as $key => $value) { 1949 if ($value == 'xmlns') { 1950 return $key; 1951 } 1952 } 1953 } 1954 else if ($this->parentNode->uid != $this->ownerDocument->uid) { 1955 return $this->parentNode->getDefaultNamespaceDeclaration(); 1956 } 1957 else { 1958 return ''; 1959 } 1960 } //getDefaultNamespaceDeclaration 1961 1962 /** 1963 * Copies all namespace declarations in scope to the namespace URI map of the current element 1964 */ 1965 function copyNamespaceDeclarationsLocally() { 1966 $nsMap = $this->getNamespaceDeclarationsInScope(); 1967 1968 //add xmlns declarations as attributes 1969 foreach ($nsMap as $key => $value) { 1970 if ($value == 'xmlns') { 1971 $this->declareDefaultNamespace($key); 1972 } 1973 else { 1974 $this->declareNamespace($value, $key); 1975 } 1976 } 1977 } //copyNamespaceDeclarationsLocally 1978 1979 /** 1980 * Adds elements with the specified tag name to a NodeList collection 1981 * @param Object The NodeList collection 1982 * @param string The namespaceURI of matching elements 1983 * @param string The localName of matching elements 1984 */ 1985 function getNamedElementsNS(&$nodeList, $namespaceURI, $localName) { 1986 if ((($namespaceURI == $this->namespaceURI) || ($namespaceURI == '*')) && 1987 (($localName == $this->localName) || ($localName == '*'))) { 1988 $nodeList->appendNode($this); 1989 } 1990 1991 $total = $this->childCount; 1992 1993 for ($i = 0; $i < $total; $i++) { 1994 if ($this->childNodes[$i]->nodeType == DOMIT_ELEMENT_NODE) { 1995 $this->childNodes[$i]->getNamedElementsNS($nodeList, $namespaceURI, $localName); 1996 } 1997 } 1998 } //getNamedElementsNS 1999 2000 /** 2001 * Returns the concatented text of the current node and its children 2002 * @return string The concatented text of the current node and its children 2003 */ 2004 function getText() { 2005 $text = ''; 2006 $numChildren = $this->childCount; 2007 2008 for ($i = 0; $i < $numChildren; $i++) { 2009 $child =& $this->childNodes[$i]; 2010 $text .= $child->getText(); 2011 } 2012 2013 return $text; 2014 } //getText 2015 2016 /** 2017 * If a child text node exists, sets the nodeValue to $data. A child text node is created if none exists 2018 * @param string The text data of the node 2019 */ 2020 function setText($data) { 2021 switch ($this->childCount) { 2022 case 1: 2023 if ($this->firstChild->nodeType == DOMIT_TEXT_NODE) { 2024 $this->firstChild->setText($data); 2025 } 2026 break; 2027 2028 case 0: 2029 $childTextNode =& $this->ownerDocument->createTextNode($data); 2030 $this->appendChild($childTextNode); 2031 break; 2032 2033 default: 2034 //do nothing. Maybe throw error??? 2035 } 2036 } //setText 2037 2038 /** 2039 * Retrieves a NodeList of child elements with the specified tag name 2040 * @param string The matching element tag name 2041 * @return Object A NodeList of found elements 2042 */ 2043 function &getElementsByTagName($tagName) { 2044 $nodeList = new DOMIT_NodeList(); 2045 $this->getNamedElements($nodeList, $tagName); 2046 2047 return $nodeList; 2048 } //getElementsByTagName 2049 2050 /** 2051 * Retrieves a NodeList of child elements with the specified namespaceURI and localName 2052 * @param string The namespaceURI 2053 * @param string The localName 2054 * @return Object A NodeList of found elements 2055 */ 2056 function &getElementsByTagNameNS($namespaceURI, $localName) { 2057 $nodeList = new DOMIT_NodeList(); 2058 $this->getNamedElementsNS($nodeList, $namespaceURI, $localName); 2059 2060 return $nodeList; 2061 } //getElementsByTagNameNS 2062 2063 /** 2064 * Returns the attribute node whose ID is given by elementId. 2065 * @param string The id of the matching element 2066 * @param boolean True if XML spec is to be strictly adhered to (only attributes xml:id are considered valid) 2067 * @return Object The found attribute or null 2068 */ 2069 function &_getElementByID($elementID, $isStrict) { 2070 if ($isStrict) { 2071 $myAttrNode =& $this->getAttributeNodeNS(DOMIT_XML_NAMESPACE, 'id'); 2072 if (($myAttrNode != null)&& ($myAttrNode->getValue() == $elementID)) return $myAttrNode; 2073 } 2074 else { 2075 $myAttrNode =& $this->getAttributeNodeNS('', 'ID'); 2076 if (($myAttrNode != null)&& ($myAttrNode->getValue() == $elementID)) return $myAttrNode; 2077 2078 $myAttrNode =& $this->getAttributeNodeNS('', 'id'); 2079 if (($myAttrNode != null)&& ($myAttrNode->getValue() == $elementID)) return $myAttrNode; 2080 } 2081 2082 $total = $this->childCount; 2083 2084 for ($i = 0; $i < $total; $i++) { 2085 if ($this->childNodes[$i]->nodeType == DOMIT_ELEMENT_NODE) { 2086 $foundNode =& $this->childNodes[$i]->_getElementByID($elementID, $isStrict); 2087 2088 if ($foundNode != null) { 2089 return $foundNode; 2090 } 2091 } 2092 } 2093 2094 $null = null; 2095 return $null; 2096 } //_getElementByID 2097 2098 /** 2099 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like expression. 2100 * @param string The query pattern 2101 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node 2102 * @return mixed A NodeList or single node that matches the pattern 2103 */ 2104 function &getElementsByPath($pattern, $nodeIndex = 0) { 2105 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_getelementsbypath.php'); 2106 2107 $gebp = new DOMIT_GetElementsByPath(); 2108 $myResponse =& $gebp->parsePattern($this, $pattern, $nodeIndex); 2109 2110 return $myResponse; 2111 } //getElementsByPath 2112 2113 /** 2114 * Retrieves an element or DOMIT_NodeList of elements corresponding to an Xpath-like attribute expression (NOT YET IMPLEMENTED!) 2115 * @param string The query pattern 2116 * @param int If a single node is to be returned (rather than the entire NodeList) the index of that node 2117 * @return mixed A NodeList or single node that matches the pattern 2118 */ 2119 function &getElementsByAttributePath($pattern, $nodeIndex = 0) { 2120 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_getelementsbypath.php'); 2121 2122 $gabp = new DOMIT_GetElementsByAttributePath(); 2123 $myResponse =& $gabp->parsePattern($this, $pattern, $nodeIndex); 2124 2125 return $myResponse; 2126 } //getElementsByAttributePath 2127 2128 /** 2129 * Adds all child nodes of the specified nodeType to the NodeList 2130 * @param Object The NodeList collection 2131 * @param string The nodeType of matching nodes 2132 */ 2133 function getTypedNodes(&$nodeList, $type) { 2134 $numChildren = $this->childCount; 2135 2136 for ($i = 0; $i < $numChildren; $i++) { 2137 $child =& $this->childNodes[$i]; 2138 2139 if ($child->nodeType == $type) { 2140 $nodeList->appendNode($child); 2141 } 2142 2143 if ($child->hasChildNodes()) { 2144 $child->getTypedNodes($nodeList, $type); 2145 } 2146 } 2147 } //getTypedNodes 2148 2149 /** 2150 * Adds all child nodes of the specified nodeValue to the NodeList 2151 * @param Object The NodeList collection 2152 * @param string The nodeValue of matching nodes 2153 */ 2154 function getValuedNodes(&$nodeList, $value) { 2155 $numChildren = $this->childCount; 2156 2157 for ($i = 0; $i < $numChildren; $i++) { 2158 $child =& $this->childNodes[$i]; 2159 2160 if ($child->nodeValue == $value) { 2161 $nodeList->appendNode($child); 2162 } 2163 2164 if ($child->hasChildNodes()) { 2165 $child->getValuedNodes($nodeList, $value); 2166 } 2167 } 2168 } //getValuedNodes 2169 2170 /** 2171 * Gets the value of the specified attribute, if it exists 2172 * @param string The attribute name 2173 * @return string The attribute value 2174 */ 2175 function getAttribute($name) { 2176 $returnNode =& $this->attributes->getNamedItem($name); 2177 2178 if ($returnNode == null) { 2179 return ''; 2180 } 2181 else { 2182 return $returnNode->getValue(); 2183 } 2184 } //getAttribute 2185 2186 /** 2187 * Gets the value of the attribute with the specified namespaceURI and localName, if it exists 2188 * @param string The namespaceURI 2189 * @param string The localName 2190 * @return string The attribute value 2191 */ 2192 function getAttributeNS($namespaceURI, $localName) { 2193 $returnNode =& $this->attributes->getNamedItemNS($namespaceURI, $localName); 2194 2195 if ($returnNode == null) { 2196 return ''; 2197 } 2198 else { 2199 return $returnNode->getValue(); 2200 } 2201 } //getAttributeNS 2202 2203 /** 2204 * Sets the value of the specified attribute; creates a new attribute if one doesn't exist 2205 * @param string The attribute name 2206 * @param string The desired attribute value 2207 */ 2208 function setAttribute($name, $value) { 2209 $returnNode =& $this->attributes->getNamedItem($name); 2210 2211 if ($returnNode == null) { 2212 $newAttr = new DOMIT_Attr($name); 2213 $newAttr->setValue($value); 2214 $this->attributes->setNamedItem($newAttr); 2215 } 2216 else { 2217 $returnNode->setValue($value); 2218 } 2219 } //setAttribute 2220 2221 /** 2222 * Sets the value of the specified attribute; creates a new attribute if one doesn't exist 2223 * @param string The attribute namespaceURI 2224 * @param string The attribute qualifiedName 2225 * @param string The desired attribute value 2226 */ 2227 function setAttributeNS($namespaceURI, $qualifiedName, $value) { 2228 //get localName 2229 $colonIndex = strpos($qualifiedName, ":"); 2230 2231 if ($colonIndex !== false) { 2232 $localName = substr($qualifiedName, ($colonIndex + 1)); 2233 } 2234 else { 2235 $localName = $qualifiedName; 2236 } 2237 2238 $returnNode =& $this->attributes->getNamedItemNS($namespaceURI, $localName); 2239 2240 if ($returnNode == null) { 2241 //create this manually in case element has no ownerDocument to reference 2242 $newAttr = new DOMIT_Attr($qualifiedName); 2243 $newAttr->prefix = substr($qualifiedName, 0, $colonIndex); 2244 $newAttr->localName = $localName; 2245 $newAttr->namespaceURI = $namespaceURI; 2246 2247 $newAttr->setValue($value); 2248 $this->attributes->setNamedItemNS($newAttr); 2249 $newAttr->ownerElement =& $this; 2250 } 2251 else { 2252 $returnNode->setValue($value); 2253 } 2254 } //setAttributeNS 2255 2256 /** 2257 * Removes the specified attribute 2258 * @param string The name of the attribute to be removed 2259 */ 2260 function removeAttribute($name) { 2261 $returnNode =& $this->attributes->removeNamedItem($name); 2262 } //removeAttribute 2263 2264 /** 2265 * Removes the specified attribute 2266 * @param string The namespaceURI of the attribute to be removed 2267 * @param string The localName of the attribute to be removed 2268 */ 2269 function removeAttributeNS($namespaceURI, $localName) { 2270 $returnNode =& $this->attributes->removeNamedItemNS($namespaceURI, $localName); 2271 unset($returnNode->ownerElement); 2272 $returnNode->ownerElement = null; 2273 } //removeAttributeNS 2274 2275 /** 2276 * Determines whether an attribute with the specified name exists 2277 * @param string The name of the attribute 2278 * @return boolean True if the attribute exists 2279 */ 2280 function hasAttribute($name) { 2281 $returnNode =& $this->attributes->getNamedItem($name); 2282 2283 return ($returnNode != null); 2284 } //hasAttribute 2285 2286 /** 2287 * Determines whether an attribute with the specified namespaceURI and localName exists 2288 * @param string The namespaceURI of the attribute 2289 * @param string The localName of the attribute 2290 * @return boolean True if the attribute exists 2291 */ 2292 function hasAttributeNS($namespaceURI, $localName) { 2293 $returnNode =& $this->attributes->getNamedItemNS($namespaceURI, $localName); 2294 2295 return ($returnNode != null); 2296 } //hasAttributeNS 2297 2298 /** 2299 * Determines whether the element has any atributes 2300 * @return boolean True if the element has any atributes 2301 */ 2302 function hasAttributes() { 2303 return ($this->attributes->getLength() > 0); 2304 } //hasChildNodes 2305 2306 /** 2307 * Gets a reference to the specified attribute node 2308 * @param string The attribute name 2309 * @return Object A reference to the found node, or null 2310 */ 2311 function &getAttributeNode($name) { 2312 $returnNode =& $this->attributes->getNamedItem($name); 2313 return $returnNode; 2314 } //getAttributeNode 2315 2316 /** 2317 * Gets a reference to the specified attribute node 2318 * @param string The attribute namespaceURI 2319 * @param string The attribute localName 2320 * @return Object A reference to the found node, or null 2321 */ 2322 function &getAttributeNodeNS($namespaceURI, $localName) { 2323 $returnNode =& $this->attributes->getNamedItemNS($namespaceURI, $localName); 2324 return $returnNode; 2325 } //getAttributeNodeNS 2326 2327 /** 2328 * Adds an attribute node to the current element 2329 * @param Object The attribute node to be added 2330 * @return Object A reference to the newly added node 2331 */ 2332 function &setAttributeNode(&$newAttr) { 2333 $returnNode =& $this->attributes->setNamedItem($newAttr); 2334 return $returnNode; 2335 } //setAttributeNode 2336 2337 /** 2338 * Adds an attribute node to the current element (namespace aware) 2339 * @param Object The attribute node to be added 2340 * @return Object A reference to the newly added node 2341 */ 2342 function &setAttributeNodeNS(&$newAttr) { 2343 $returnNode =& $this->attributes->setNamedItemNS($newAttr); 2344 $newAttr->ownerElement =& $this; 2345 return $returnNode; 2346 } //setAttributeNodeNS 2347 2348 /** 2349 * Removes an attribute node from the current element 2350 * @param Object The attribute node to be removed 2351 * @return Object A reference to the removed node 2352 */ 2353 function &removeAttributeNode(&$oldAttr) { 2354 $attrName = $oldAttr->getName(); 2355 $returnNode =& $this->attributes->removeNamedItem($attrName); 2356 2357 if ($returnNode == null) { 2358 DOMIT_DOMException::raiseException(DOMIT_NOT_FOUND_ERR, 2359 'Target attribute not found.'); 2360 } 2361 else { 2362 return $returnNode; 2363 } 2364 } //removeAttributeNode 2365 2366 /** 2367 * Collapses adjacent text nodes in entire element subtree 2368 */ 2369 function normalize() { 2370 if ($this->hasChildNodes()) { 2371 $currNode =& $this->childNodes[0]; 2372 2373 while ($currNode->nextSibling != null) { 2374 $nextNode =& $currNode->nextSibling; 2375 2376 if (($currNode->nodeType == DOMIT_TEXT_NODE) && 2377 ($nextNode->nodeType == DOMIT_TEXT_NODE)) { 2378 2379 $currNode->nodeValue .= $nextNode->nodeValue; 2380 $this->removeChild($nextNode); 2381 } 2382 else { 2383 $currNode->normalize(); 2384 } 2385 2386 if ($currNode->nextSibling != null) { 2387 $currNode =& $currNode->nextSibling; 2388 } 2389 } 2390 } 2391 } //normalize 2392 2393 /** 2394 * Generates an array representation of the node and its children 2395 * @return Array A representation of the node and its children 2396 */ 2397 function toArray() { 2398 $arReturn = array($this->nodeName => array("attributes" => $this->attributes->toArray())); 2399 $total = $this->childCount; 2400 2401 for ($i = 0; $i < $total; $i++) { 2402 $arReturn[$this->nodeName][$i] = $this->childNodes[$i]->toArray(); 2403 } 2404 2405 return $arReturn; 2406 } //toArray 2407 2408 /** 2409 * Copies a node and/or its children 2410 * @param boolean True if all child nodes are also to be cloned 2411 * @return Object A copy of the node and/or its children 2412 */ 2413 function &cloneNode($deep = false) { 2414 $className = get_class($this); 2415 $clone = new $className($this->nodeName); 2416 2417 $clone->attributes =& $this->attributes->createClone($deep); 2418 2419 if ($this->namespaceURI) { 2420 $clone->namespaceURI = $this->namespaceURI; 2421 $clone->localName = $this->localName; 2422 } 2423 2424 if ($deep) { 2425 $total = $this->childCount; 2426 2427 for ($i = 0; $i < $total; $i++) { 2428 $currentChild =& $this->childNodes[$i]; 2429 $clone->appendChild($currentChild->cloneNode($deep)); 2430 } 2431 } 2432 2433 return $clone; 2434 } //cloneNode 2435 2436 /** 2437 * Generates a string representation of the node and its children 2438 * @param boolean True if HTML readable output is desired 2439 * @param boolean True if illegal xml characters in text nodes and attributes should be converted to entities 2440 * @return string The string representation 2441 */ 2442 function toString($htmlSafe = false, $subEntities = false) { 2443 $result = '<' . $this->nodeName; 2444 $result .= $this->attributes->toString(false, $subEntities); 2445 2446 if ($this->ownerDocument->isNamespaceAware) { 2447 foreach ($this->namespaceURIMap as $key => $value) { 2448 $result .= ' xmlns:' . $value . '="' . $key . '"'; 2449 } 2450 } 2451 2452 //get children 2453 $myNodes =& $this->childNodes; 2454 $total = count($myNodes); 2455 2456 if ($total != 0) { 2457 $result .= '>'; 2458 2459 for ($i = 0; $i < $total; $i++) { 2460 $child =& $myNodes[$i]; 2461 $result .= $child->toString(false, $subEntities); 2462 } 2463 2464 $result .= '</' . $this->nodeName . '>'; 2465 } 2466 else { 2467 if ($this->ownerDocument->doExpandEmptyElementTags) { 2468 if (in_array($this->nodeName, $this->ownerDocument->expandEmptyElementExceptions)) { 2469 $result .= ' />'; 2470 } 2471 else { 2472 $result .= '></' . $this->nodeName . '>'; 2473 } 2474 } 2475 else { 2476 if (in_array($this->nodeName, $this->ownerDocument->expandEmptyElementExceptions)) { 2477 $result .= '></' . $this->nodeName . '>'; 2478 } 2479 else { 2480 $result .= ' />'; 2481 } 2482 } 2483 } 2484 2485 if ($htmlSafe) $result = $this->forHTML($result); 2486 2487 return $result; 2488 } //toString 2489 } //DOMIT_Element 2490 2491 /** 2492 * A parent class for Text and CDATA Section nodes 2493 * 2494 * @package domit-xmlparser 2495 * @subpackage domit-xmlparser-main 2496 * @author John Heinstein <johnkarl@nbnet.nb.ca> 2497 */ 2498 class DOMIT_CharacterData extends DOMIT_Node { 2499 /** 2500 * Prevents direct instantiation of DOMIT_CharacterData class 2501 * @abstract 2502 */ 2503 function DOMIT_CharacterData() { 2504 DOMIT_DOMException::raiseException(DOMIT_ABSTRACT_CLASS_INSTANTIATION_ERR, 2505 'Cannot instantiate abstract class DOMIT_CharacterData'); 2506 } //DOMIT_CharacterData 2507 2508 /** 2509 * Gets the node value of the current text node 2510 * @return string The node value of the current text node 2511 */ 2512 function getData() { 2513 return $this->nodeValue; 2514 } //getData 2515 2516 /** 2517 * Sets the text contained in the current node to $data. 2518 * @param string The text data of the node 2519 */ 2520 function setData($data) { 2521 $this->nodeValue = $data; 2522 } //setData 2523 2524 2525 /** 2526 * Gets the length of the text in the current node 2527 * @return int The length of the text in the current node 2528 */ 2529 function getLength() { 2530 return strlen($this->nodeValue); 2531 } //getLength 2532 2533 /** 2534 * Gets a subset of the current node text 2535 * @param int The starting point of the substring 2536 * @param int The length of the substring 2537 * @return string The subset of the current node text 2538 */ 2539 function substringData($offset, $count) { 2540 $totalChars = $this->getLength(); 2541 2542 if (($offset < 0) || (($offset + $count) > $totalChars)) { 2543 2544 DOMIT_DOMException::raiseException(DOMIT_INDEX_SIZE_ERR, 2545 'Character Data index out of bounds.'); 2546 2547 } 2548 else { 2549 $data = $this->getData(); 2550 return substr($data, $offset, $count); 2551 } 2552 } //substringData 2553 2554 /** 2555 * Appends the specified text to the current node text 2556 * @param string The text to be appended 2557 */ 2558 function appendData($arg) { 2559 $this->setData($this->getData() . $arg); 2560 } //appendData 2561 2562 /** 2563 * Inserts text at the sepecified offset 2564 * @param int The insertion point 2565 * @param string The text to be inserted 2566 */ 2567 function insertData($offset, $arg) { 2568 $totalChars = $this->getLength(); 2569 2570 if (($offset < 0) || ($offset > $totalChars)) { 2571 2572 DOMIT_DOMException::raiseException(DOMIT_INDEX_SIZE_ERR, 2573 'Character Data index out of bounds.'); 2574 2575 } 2576 else { 2577 $data = $this->getData(); 2578 $pre = substr($data, 0, $offset); 2579 $post = substr($data, $offset); 2580 2581 $this->setData(($pre . $arg . $post)); 2582 } 2583 } //insertData 2584 2585 /** 2586 * Deletes a subset of the current node text 2587 * @param int The starting point of the deletion 2588 * @param int The length of the deletion 2589 */ 2590 function deleteData($offset, $count) { 2591 $totalChars = $this->getLength(); 2592 2593 if (($offset < 0) || (($offset + $count) > $totalChars)) { 2594 2595 DOMIT_DOMException::raiseException(DOMIT_INDEX_SIZE_ERR, 2596 'Character Data index out of bounds.'); 2597 2598 } 2599 else { 2600 $data = $this->getData(); 2601 $pre = substr($data, 0, $offset); 2602 $post = substr($data, ($offset + $count)); 2603 2604 $this->setData(($pre . $post)); 2605 } 2606 } //substringData 2607 2608 /** 2609 * Replaces a subset of the current node text with the specified text 2610 * @param int The starting point of the replacement 2611 * @param int The length of the replacement 2612 * @param string The replacement text 2613 */ 2614 function replaceData($offset, $count, $arg) { 2615 $totalChars = $this->getLength(); 2616 2617 if (($offset < 0) || (($offset + $count) > $totalChars)) { 2618 2619 DOMIT_DOMException::raiseException(DOMIT_INDEX_SIZE_ERR, 2620 'Character Data index out of bounds.'); 2621 2622 } 2623 else { 2624 $data = $this->getData(); 2625 $pre = substr($data, 0, $offset); 2626 $post = substr($data, ($offset + $count)); 2627 2628 $this->setData(($pre . $arg . $post)); 2629 } 2630 } //replaceData 2631 } //DOMIT_CharacterData 2632 2633 /** 2634 * A class representing the DOM Text Node 2635 * 2636 * @package domit-xmlparser 2637 * @subpackage domit-xmlparser-main 2638 * @author John Heinstein <johnkarl@nbnet.nb.ca> 2639 */ 2640 class DOMIT_TextNode extends DOMIT_CharacterData { 2641 /** 2642 * DOM Text Node constructor 2643 * @param string The text of the node 2644 */ 2645 function DOMIT_TextNode($data) { 2646 $this->_constructor(); 2647 $this->nodeType = DOMIT_TEXT_NODE; 2648 $this->nodeName = '#text'; 2649 $this->setText($data); 2650 } //DOMIT_TextNode 2651 2652 /** 2653 * Returns the text contained in the current node 2654 * @return string The text of the current node 2655 */ 2656 function getText() { 2657 return $this->nodeValue; 2658 } //getText 2659 2660 /** 2661 * Sets the text contained in the current node to $data. 2662 * @param string The text data of the node 2663 */ 2664 function setText($data) { 2665 $this->nodeValue = $data; 2666 } //setText 2667 2668 /** 2669 * Splits a single node into multiple nodes, based on the specified offset 2670 * @param int The offset point for the split 2671 * @return Object The newly created text node 2672 */ 2673 function &splitText($offset) { 2674 $totalChars = $this->getLength(); 2675 2676 if (($offset < 0) || ($offset > $totalChars)) { 2677 2678 DOMIT_DOMException::raiseException(DOMIT_INDEX_SIZE_ERR, 2679 'Character Data index out of bounds.'); 2680 2681 } 2682 else { 2683 $data = $this->getData(); 2684 $pre = substr($data, 0, $offset); 2685 $post = substr($data, $offset); 2686 2687 $this->setText($pre); 2688 2689 //create new text node 2690 $className = get_class($this); 2691 $newTextNode = new $className($post); 2692 $newTextNode->ownerDocument =& $this->ownerDocument; 2693 2694 if ($this->parentNode->lastChild->uid == $this->uid) { 2695 $this->parentNode->appendChild($newTextNode); 2696 } 2697 else { 2698 $this->parentNode->insertBefore($newTextNode, $this); 2699 } 2700 2701 return $newTextNode; 2702 } 2703 } //splitText 2704 2705 /** 2706 * Generates an array representation of the node and its children 2707 * @return Array A representation of the node and its children 2708 */ 2709 function toArray() { 2710 return $this->toString(); 2711 } //toArray 2712 2713 /** 2714 * Copies a node and/or its children 2715 * @param boolean True if all child nodes are also to be cloned 2716 * @return Object A copy of the node and/or its children 2717 */ 2718 function &cloneNode($deep = false) { 2719 $className = get_class($this); 2720 $clone = new $className($this->nodeValue); 2721 2722 return $clone; 2723 } //cloneNode 2724 2725 /** 2726 * Generates a string representation of the node and its children 2727 * @param boolean True if HTML readable output is desired 2728 * @param boolean True if illegal xml characters should be converted to entities 2729 * @return string The string representation 2730 */ 2731 function toString($htmlSafe = false, $subEntities = false) { 2732 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_utilities.php'); 2733 global $DOMIT_defined_entities_flip; 2734 2735 $result = $subEntities ? DOMIT_Utilities::convertEntities($this->nodeValue, 2736 $DOMIT_defined_entities_flip) : $this->nodeValue; 2737 2738 if ($htmlSafe) $result = $this->forHTML($result); 2739 2740 return $result; 2741 } //toString 2742 } //DOMIT_TextNode 2743 2744 /** 2745 * A class representing the DOM CDATA Section 2746 * 2747 * @package domit-xmlparser 2748 * @subpackage domit-xmlparser-main 2749 * @author John Heinstein <johnkarl@nbnet.nb.ca> 2750 */ 2751 class DOMIT_CDATASection extends DOMIT_TextNode { 2752 /** 2753 * DOM CDATA Section node constructor 2754 * @param string The text of the node 2755 */ 2756 function DOMIT_CDATASection($data) { 2757 $this->_constructor(); 2758 $this->nodeType = DOMIT_CDATA_SECTION_NODE; 2759 $this->nodeName = '#cdata-section'; 2760 $this->setText($data); 2761 } //DOMIT_CDATASection 2762 2763 /** 2764 * Generates a string representation of the node and its children 2765 * @param boolean True if HTML readable output is desired 2766 * @param boolean True if illegal xml characters should be converted to entities 2767 * @return string The string representation 2768 */ 2769 function toString($htmlSafe = false, $subEntities = false) { 2770 $result = '<![CDATA['; 2771 $result .= $subEntities ? str_replace("]]>", "]]>", $this->nodeValue) : 2772 $this->nodeValue; 2773 $result .= ']]>'; 2774 2775 if ($htmlSafe) $result = $this->forHTML($result); 2776 2777 return $result; 2778 } //toString 2779 } //DOMIT_CDATASection 2780 2781 /** 2782 * A class representing the Attr node 2783 * 2784 * @package domit-xmlparser 2785 * @subpackage domit-xmlparser-main 2786 * @author John Heinstein <johnkarl@nbnet.nb.ca> 2787 */ 2788 class DOMIT_Attr extends DOMIT_Node { 2789 /** @var boolean True if the attribute has been modified since parsing (NOT YET IMPLEMENTED!) */ 2790 var $specified = false; 2791 /** @var Object A reference to the element to which the attribute is assigned */ 2792 var $ownerElement = null; 2793 2794 /** 2795 * DOM Attr node constructor 2796 * @param string The name of the attribute 2797 */ 2798 function DOMIT_Attr($name) { 2799 $this->_constructor(); 2800 $this->nodeType = DOMIT_ATTRIBUTE_NODE; 2801 $this->nodeName =$name; 2802 } //DOMIT_Attr 2803 2804 /** 2805 * Returns the name of the attribute 2806 * @return string The name of the attribute 2807 */ 2808 function getName() { 2809 return $this->nodeName; 2810 } //getName 2811 2812 /** 2813 * Indicates whether an attribute has been modified since parsing 2814 * @return boolean True if the node has been modified 2815 */ 2816 function getSpecified() { 2817 return $this->specified; 2818 } //getSpecified 2819 2820 /** 2821 * Returns the value of the attribute 2822 * @return string The value of the attribute 2823 */ 2824 function getValue() { 2825 return $this->nodeValue; 2826 } //getValue 2827 2828 /** 2829 * Sets the value of the attribute 2830 * @param string The value of the attribute 2831 */ 2832 function setValue($value) { 2833 $this->nodeValue = $value; 2834 } //setValue 2835 2836 /** 2837 * Returns the text contained in the current node 2838 * @return string The text of the current node 2839 */ 2840 function getText() { 2841 return $this->nodeValue; 2842 } //getText 2843 2844 /** 2845 * Sets the text contained in the current node to $data. 2846 * @param string The text data of the node 2847 */ 2848 function setText($data) { 2849 $this->nodeValue = $data; 2850 } //setText 2851 2852 /** 2853 * Copies a node and/or its children 2854 * @param boolean True if all child nodes are also to be cloned 2855 * @return Object A copy of the node and/or its children 2856 */ 2857 function &cloneNode($deep = false) { 2858 $className = get_class($this); 2859 $clone = new $className($this->nodeName); 2860 $clone->nodeValue = $this->nodeValue; 2861 2862 if ($this->namespaceURI) { 2863 $clone->namespaceURI = $this->namespaceURI; 2864 $clone->localName = $this->localName; 2865 } 2866 2867 return $clone; 2868 } //cloneNode 2869 2870 /** 2871 * Generates a string representation of the node and its children 2872 * @param boolean True if HTML readable output is desired 2873 * @param boolean True if HTML entities should be substituted 2874 * @return string The string representation 2875 */ 2876 function toString($htmlSafe = false, $subEntities = false) { 2877 require_once (DOMIT_INCLUDE_PATH . 'xml_domit_utilities.php'); 2878 global $DOMIT_defined_entities_flip; 2879 2880 $result = ' ' . $this->nodeName . '="'; 2881 $result .= $subEntities ? DOMIT_Utilities::convertEntities($this->nodeValue, 2882 $DOMIT_defined_entities_flip) : $this->nodeValue; 2883 $result .= '"'; 2884 2885 if ($htmlSafe) $result = $this->forHTML($result); 2886 2887 return $result; 2888 } //toString 2889 } //DOMIT_Attr 2890 2891 /** 2892 * A class representing the DOM Document Fragment node 2893 * 2894 * @package domit-xmlparser 2895 * @subpackage domit-xmlparser-main 2896 * @author John Heinstein <johnkarl@nbnet.nb.ca> 2897 */ 2898 class DOMIT_DocumentFragment extends DOMIT_ChildNodes_Interface { 2899 /** 2900 * DOM Document Fragment node constructor 2901 */ 2902 function DOMIT_DocumentFragment() { 2903 $this->_constructor(); 2904 $this->nodeType = DOMIT_DOCUMENT_FRAGMENT_NODE; 2905 $this->nodeName ='#document-fragment'; 2906 $this->nodeValue = null; 2907 $this->childNodes = array(); 2908 } //DOMIT_DocumentFragment 2909 2910 /** 2911 * Generates an array representation of the node and its children 2912 * @return Array A representation of the node and its children 2913 */ 2914 function toArray() { 2915 $arReturn = array(); 2916 $total = $this->childCount; 2917 2918 for ($i = 0; $i < $total; $i++) { 2919 $arReturn[$i] = $this->childNodes[$i]->toArray(); 2920 } 2921 2922 return $arReturn; 2923 } //toArray 2924 2925 /** 2926 * Copies a node and/or its children 2927 * @param boolean True if all child nodes are also to be cloned 2928 * @return Object A copy of the node and/or its children 2929 */ 2930 function &cloneNode($deep = false) { 2931 $className = get_class($this); 2932 $clone = new $className(); 2933 2934 if ($deep) { 2935 $total = $this->childCount; 2936 2937 for ($i = 0; $i < $total; $i++) { 2938 $currentChild =& $this->childNodes[$i]; 2939 $clone->appendChild($currentChild->cloneNode($deep)); 2940 } 2941 } 2942 2943 return $clone; 2944 } //cloneNode 2945 2946 /** 2947 * Generates a string representation of the node and its children 2948 * @param boolean True if HTML readable output is desired 2949 * @return string The string representation 2950 */ 2951 function toString($htmlSafe = false, $subEntities = false) { 2952 //get children 2953 $result = ''; 2954 $myNodes =& $this->childNodes; 2955 $total = count($myNodes); 2956 2957 if ($total != 0) { 2958 for ($i = 0; $i < $total; $i++) { 2959 $child =& $myNodes[$i]; 2960 $result .= $child->toString(false, $subEntities); 2961 } 2962 } 2963 2964 if ($htmlSafe) $result = $this->forHTML($result); 2965 2966 return $result; 2967 } //toString 2968 } //DOMIT_DocumentFragment 2969 2970 /** 2971 * A class representing the DOM Comment node 2972 * 2973 * @package domit-xmlparser 2974 * @subpackage domit-xmlparser-main 2975 * @author John Heinstein <johnkarl@nbnet.nb.ca> 2976 */ 2977 class DOMIT_Comment extends DOMIT_CharacterData { 2978 /** 2979 * DOM Comment node constructor 2980 * @param string The 2981 */ 2982 function DOMIT_Comment($nodeValue) { 2983 $this->_constructor(); 2984 $this->nodeType = DOMIT_COMMENT_NODE; 2985 $this->nodeName = '#comment'; 2986 $this->nodeValue = $nodeValue; 2987 } //DOMIT_Comment 2988 2989 /** 2990 * Returns the text contained in the current node 2991 * @return string The text of the current node 2992 */ 2993 function getText() { 2994 return $this->nodeValue; 2995 } //getText 2996 2997 /** 2998 * Sets the text contained in the current node to $data. 2999 * @param string The text data of the node 3000 */ 3001 function setText($data) { 3002 $this->nodeValue = $data; 3003 } //setText 3004 3005 /** 3006 * Generates an array representation of the node and its children 3007 * @return Array A representation of the node and its children 3008 */ 3009 function toArray() { 3010 return $this->toString(); 3011 } //toArray 3012 3013 /** 3014 * Copies a node and/or its children 3015 * @param boolean True if all child nodes are also to be cloned 3016 * @return Object A copy of the node and/or its children 3017 */ 3018 function &cloneNode($deep = false) { 3019 $className = get_class($this); 3020 $clone = new $className($this->nodeValue); 3021 3022 return $clone; 3023 } //cloneNode 3024 3025 /** 3026 * Generates a string representation of the node and its children 3027 * @param boolean True if HTML readable output is desired 3028 * @return string The string representation 3029 */ 3030 function toString($htmlSafe = false) { 3031 $result = '<!--' . $this->nodeValue . '-->'; 3032 3033 if ($htmlSafe) $result = $this->forHTML($result); 3034 3035 return $result; 3036 } //toString 3037 } //DOMIT_Comment 3038 3039 /** 3040 * A class representing the DOM Processing Instruction node 3041 * 3042 * @package domit-xmlparser 3043 * @subpackage domit-xmlparser-main 3044 * @author John Heinstein <johnkarl@nbnet.nb.ca> 3045 */ 3046 class DOMIT_ProcessingInstruction extends DOMIT_Node { 3047 /** 3048 * DOM Processing Instruction node constructor 3049 * @param string The 3050 */ 3051 function DOMIT_ProcessingInstruction($target, $data) { 3052 $this->_constructor(); 3053 $this->nodeType = DOMIT_PROCESSING_INSTRUCTION_NODE; 3054 $this->nodeName = $target; 3055 $this->nodeValue = $data; 3056 } //DOMIT_ProcessingInstruction 3057 3058 /** 3059 * Returns the processing instruction target 3060 * @return string The processing instruction target 3061 */ 3062 function getTarget() { 3063 return $this->nodeName; 3064 } //getTarget 3065 3066 /** 3067 * Returns the processing instruction data 3068 * @return string The processing instruction data 3069 */ 3070 function getData() { 3071 return $this->nodeValue; 3072 } //getData 3073 3074 /** 3075 * Returns the text contained in the current node 3076 * @return string The text of the current node 3077 */ 3078 function getText() { 3079 return ($this->nodeName . ' ' . $this->nodeValue); 3080 } //getText 3081 3082 /** 3083 * Generates an array representation of the node and its children 3084 * @return Array A representation of the node and its children 3085 */ 3086 function toArray() { 3087 return $this->toString(); 3088 } //toArray 3089 3090 /** 3091 * Copies a node and/or its children 3092 * @param boolean True if all child nodes are also to be cloned 3093 * @return Object A copy of the node and/or its children 3094 */ 3095 function &cloneNode($deep = false) { 3096 $className = get_class($this); 3097 $clone = new $className($this->nodeName, $this->nodeValue); 3098 3099 return $clone; 3100 } //cloneNode 3101 3102 /** 3103 * Generates a string representation of the node and its children 3104 * @param boolean True if HTML readable output is desired 3105 * @return string The string representation 3106 */ 3107 function toString($htmlSafe = false) { 3108 $result = '<' . '?' . $this->nodeName . ' ' . $this->nodeValue . '?' . '>'; 3109 3110 if ($htmlSafe) $result = $this->forHTML($result); 3111 3112 return $result; 3113 } //toString 3114 } //DOMIT_ProcessingInstruction 3115 3116 /** 3117 * A class representing the DOM Document Type node 3118 * 3119 * @package domit-xmlparser 3120 * @subpackage domit-xmlparser-main 3121 * @author John Heinstein <johnkarl@nbnet.nb.ca> 3122 */ 3123 class DOMIT_DocumentType extends DOMIT_Node { 3124 /** @var string The doctype name */ 3125 var $name; 3126 /** @var Object True if the entity has been modified since parsing (NOT YET IMPLEMENTED!) */ 3127 var $entities; 3128 /** @var Object A NodeList of notation nodes (NOT YET IMPLEMENTED!) */ 3129 var $notations; 3130 /** @var Object A NodeList of elements (NOT YET IMPLEMENTED!) */ 3131 var $elements; 3132 /** @var string The full text of the doctype */ 3133 var $text; 3134 /** @var string The public identifier of the external subset */ 3135 var $publicID; 3136 /** @var string The system identifier of the external subset */ 3137 var $systemID; 3138 /** @var string The full text of internal subset */ 3139 var $internalSubset; 3140 3141 /** 3142 * DOM Document Type node constructor 3143 * @param string The 3144 */ 3145 function DOMIT_DocumentType($name, $text) { 3146 $this->_constructor(); 3147 $this->nodeType = DOMIT_DOCUMENT_TYPE_NODE; 3148 $this->nodeName = $name; 3149 $this->name = $name; 3150 $this->entities = null; //implement later 3151 $this->notations = null; //implement later 3152 $this->elements = null; //implement later 3153 $this->text = $text; 3154 } //DOMIT_DocumentType 3155 3156 /** 3157 * Returns the text contained in the current node 3158 * @return string The text of the current node 3159 */ 3160 function getText() { 3161 return $this->text; 3162 } //getText 3163 3164 /** 3165 * Returns the name of the doctype node 3166 * @return string The name of the doctype node 3167 */ 3168 function getName() { 3169 return $this->name; 3170 } //getName 3171 3172 /** 3173 * Generates an array representation of the node and its children 3174 * @return Array A representation of the node and its children 3175 */ 3176 function toArray() { 3177 return $this->toString(); 3178 } //toArray 3179 3180 /** 3181 * Copies a node and/or its children 3182 * @param boolean True if all child nodes are also to be cloned 3183 * @return Object A copy of the node and/or its children 3184 */ 3185 function &cloneNode($deep = false) { 3186 $className = get_class($this); 3187 $clone = new $className($this->nodeName, $this->text); 3188 3189 return $clone; 3190 } //cloneNode 3191 3192 /** 3193 * Generates a string representation of the node and its children 3194 * @param boolean True if HTML readable output is desired 3195 * @return string The string representation 3196 */ 3197 function toString($htmlSafe = false) { 3198 $result = $this->text; 3199 3200 if ($htmlSafe) $result = $this->forHTML($result); 3201 3202 return $result; 3203 } //toString 3204 } //DOMIT_DocumentType 3205 3206 3207 /** 3208 * A class representing the DOM Notation node (NOT YET IMPLEMENTED!) 3209 * 3210 * @package domit-xmlparser 3211 * @subpackage domit-xmlparser-main 3212 * @author John Heinstein <johnkarl@nbnet.nb.ca> 3213 */ 3214 class DOMIT_Notation extends DOMIT_Node { 3215 /** 3216 * DOM Notation node constructor (NOT YET IMPLEMENTED!) 3217 */ 3218 function DOMIT_Notation() { 3219 DOMIT_DOMException::raiseException(DOMIT_NOT_SUPPORTED_ERR, 3220 'Cannot instantiate DOMIT_Notation class. Notation nodes not yet supported.'); 3221 } //DOMIT_Notation 3222 } //DOMIT_Notation 3223 3224 /** 3225 * Manages the generation of a DOMIT! document from SAX events 3226 * 3227 * @package domit-xmlparser 3228 * @subpackage domit-xmlparser-main 3229 * @author John Heinstein <johnkarl@nbnet.nb.ca> 3230 */ 3231 class DOMIT_Parser { 3232 /** @var Object A reference to the resulting xmldoc */ 3233 var $xmlDoc = null; 3234 /** @var Object A reference to the current node in the parsing process */ 3235 var $currentNode = null; 3236 /** @var Object A reference to the last child in the parsing process */ 3237 var $lastChild = null; 3238 /** @var boolean True if currently parsing a CDATA Section */ 3239 var $inCDATASection = false; //flag for Expat 3240 /** @var boolean True if currently parsing a Text node */ 3241 var $inTextNode = false; 3242 /** @var boolean True is CDATA Section nodes are not to be converted into Text nodes */ 3243 var $preserveCDATA; 3244 /** @var string A container for holding the currently parsed text data */ 3245 var $parseContainer = ''; 3246 /** @var string The current docutype text */ 3247 var $parseItem = ''; 3248 /** @var boolean True if waiting for an element to which to apply namespace declaration(s) */ 3249 var $waitingForElementToDeclareNamespaces = false; 3250 /** @var boolean True if waiting for an element to which to apply namespace declaration(s) */ 3251 var $tempNamespaceURIMap = array(); 3252 3253 /** 3254 * Parses xml text using Expat 3255 * @param Object A reference to the DOM document that the xml is to be parsed into 3256 * @param string The text to be parsed 3257 * @param boolean True if CDATA Section nodes are not to be converted into Text nodes 3258 * @return boolean True if the parsing is successful 3259 */ 3260 function parse (&$myXMLDoc, $xmlText, $preserveCDATA = true) { 3261 $this->xmlDoc =& $myXMLDoc; 3262 $this->lastChild =& $this->xmlDoc; 3263 3264 $this->preserveCDATA = $preserveCDATA; 3265 3266 //create instance of expat parser (should be included in php distro) 3267 if (version_compare(phpversion(), '5.0', '<=')) { 3268 if ($this->xmlDoc->isNamespaceAware) { 3269 $parser = xml_parser_create_ns(''); 3270 } 3271 else { 3272 $parser = xml_parser_create(''); 3273 } 3274 } 3275 else { 3276 if ($this->xmlDoc->isNamespaceAware) { 3277 $parser = xml_parser_create_ns(); 3278 } 3279 else { 3280 $parser = xml_parser_create(); 3281 } 3282 } 3283 3284 //set handlers for SAX events 3285 xml_set_object($parser, $this); 3286 xml_set_character_data_handler($parser, 'dataElement'); 3287 xml_set_default_handler($parser, 'defaultDataElement'); 3288 xml_set_notation_decl_handler($parser, 'notationElement'); 3289 xml_set_processing_instruction_handler($parser, 'processingInstructionElement'); 3290 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 3291 3292 if (!$this->xmlDoc->preserveWhitespace) { 3293 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 3294 } 3295 else { 3296 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); 3297 } 3298 3299 if ($this->xmlDoc->isNamespaceAware) { 3300 xml_set_start_namespace_decl_handler($parser, 'startNamespaceDeclaration'); 3301 xml_set_end_namespace_decl_handler($parser, 'endNamespaceDeclaration'); 3302 xml_set_element_handler($parser, 'startElementNS', 'endElement'); 3303 $this->xmlDoc->namespaceURIMap[DOMIT_XML_NAMESPACE] = 'xml'; 3304 } 3305 else { 3306 xml_set_element_handler($parser, 'startElement', 'endElement'); 3307 } 3308 3309 //parse out whitespace - (XML_OPTION_SKIP_WHITE = 1 does not 3310 //seem to work consistently across versions of PHP and Expat 3311 if (!$this->xmlDoc->preserveWhitespace) { 3312 $xmlText = eregi_replace('>' . "[[:space:]]+" . '<' , '><', $xmlText); 3313 } 3314 3315 $success = xml_parse($parser, $xmlText); 3316 3317 $this->xmlDoc->errorCode = xml_get_error_code($parser); 3318 $this->xmlDoc->errorString = xml_error_string($this->xmlDoc->errorCode); 3319 3320 xml_parser_free($parser); 3321 3322 return $success; 3323 } //parse 3324 3325 /** 3326 * Parses xml text using SAXY 3327 * @param Object A reference to the DOM document that the xml is to be parsed into 3328 * @param string The text to be parsed 3329 * @param boolean True if CDATA Section nodes are not to be converted into Text nodes 3330 * @return boolean True if the parsing is successful 3331 */ 3332 function parseSAXY(&$myXMLDoc, $xmlText, $preserveCDATA = true, $definedEntities) { 3333 require_once (DOMIT_INCLUDE_PATH . 'xml_saxy_parser.php'); 3334 3335 $this->xmlDoc =& $myXMLDoc; 3336 $this->lastChild =& $this->xmlDoc; 3337 3338 //create instance of SAXY parser 3339 $parser = new SAXY_Parser(); 3340 $parser->appendEntityTranslationTable($definedEntities); 3341 3342 //not yet implemented in SAXY!!! 3343 $parser->preserveWhitespace = $this->xmlDoc->preserveWhitespace; 3344 3345 if ($this->xmlDoc->isNamespaceAware) { 3346 $parser->setNamespaceAwareness(true); 3347 $parser->xml_set_start_namespace_decl_handler(array(&$this, 'startNamespaceDeclaration')); 3348 $parser->xml_set_end_namespace_decl_handler(array(&$this, 'endNamespaceDeclaration')); 3349 $parser->xml_set_element_handler(array(&$this, 'startElementNS'), array(&$this, 'endElement')); 3350 $this->xmlDoc->namespaceURIMap[DOMIT_XML_NAMESPACE] = 'xml'; 3351 } 3352 else { 3353 $parser->xml_set_element_handler(array(&$this, 'startElement'), array(&$this, 'endElement')); 3354 } 3355 3356 $parser->xml_set_character_data_handler(array(&$this, 'dataElement')); 3357 $parser->xml_set_doctype_handler(array(&$this, 'doctypeElement')); 3358 $parser->xml_set_comment_handler(array(&$this, 'commentElement')); 3359 $parser->xml_set_processing_instruction_handler(array(&$this, 'processingInstructionElement')); 3360 3361 if ($preserveCDATA) { 3362 $parser->xml_set_cdata_section_handler(array(&$this, 'cdataElement')); 3363 } 3364 3365 $success = $parser->parse($xmlText); 3366 3367 $this->xmlDoc->errorCode = $parser->xml_get_error_code(); 3368 $this->xmlDoc->errorString = $parser->xml_error_string($this->xmlDoc->errorCode); 3369 3370 return $success; 3371 } //parseSAXY 3372 3373 /** 3374 * Generates and appends a new text node from the parseContainer text 3375 */ 3376 function dumpTextNode() { 3377 $currentNode =& $this->xmlDoc->createTextNode($this->parseContainer); 3378 $this->lastChild->appendChild($currentNode); 3379 $this->inTextNode = false; 3380 $this->parseContainer = ''; 3381 } //dumpTextNode 3382 3383 /** 3384 * Catches a start element event and processes the data 3385 * @param Object A reference to the current SAX parser 3386 * @param string The tag name of the current element 3387 * @param Array An array of the element attributes 3388 */ 3389 function startElement(&$parser, $name, $attrs) { 3390 if ($this->inTextNode) { 3391 $this->dumpTextNode(); 3392 } 3393 3394 $currentNode =& $this->xmlDoc->createElement($name); 3395 $this->lastChild->appendChild($currentNode); 3396 3397 reset ($attrs); 3398 3399 while (list($key, $value) = each ($attrs)) { 3400 $currentNode->setAttribute($key, $value); 3401 } 3402 3403 $this->lastChild =& $currentNode; 3404 } //startElement 3405 3406 /** 3407 * Catches a start element event and processes the data 3408 * @param Object A reference to the current SAX parser 3409 * @param string The tag name of the current element 3410 * @param Array An array of the element attributes 3411 */ 3412 function startElementNS(&$parser, $name, $attrs) { 3413 if ($this->inTextNode) { 3414 $this->dumpTextNode(); 3415 } 3416 3417 $colonIndex = strrpos($name, ":"); 3418 3419 if ($colonIndex !== false) { 3420 //force to lower case because Expat for some reason forces to upper case 3421 $namespaceURI = strtolower(substr($name, 0, $colonIndex)); 3422 $prefix = $this->xmlDoc->namespaceURIMap[$namespaceURI]; 3423 3424 if ($prefix != '') { 3425 $qualifiedName = $prefix . ":" . substr($name, ($colonIndex + 1)); 3426 } 3427 else { 3428 $qualifiedName = substr($name, ($colonIndex + 1)); 3429 } 3430 } 3431 else { 3432 $namespaceURI = ''; 3433 $qualifiedName = $name; 3434 } 3435 3436 $currentNode =& $this->xmlDoc->createElementNS($namespaceURI, $qualifiedName); 3437 $this->lastChild->appendChild($currentNode); 3438 3439 3440 //add attributes 3441 reset ($attrs); 3442 3443 while (list($key, $value) = each ($attrs)) { 3444 $colonIndex = strrpos($key, ":"); 3445 3446 if ($colonIndex !== false) { 3447 //force to lower case because Expat for some reason forces to upper case 3448 $namespaceURI = strtolower(substr($key, 0, $colonIndex)); 3449 3450 $qualifiedName = $this->xmlDoc->namespaceURIMap[$namespaceURI] . 3451 ":" . substr($key, ($colonIndex + 1));; 3452 } 3453 else { 3454 //if containing element has a namespace, technically 3455 //attribute namespace should be added here, but we'll do it elsewhere 3456 //so toNormalizedString outputs the same things as is input 3457 $namespaceURI = ''; 3458 $qualifiedName = $key; 3459 } 3460 3461 $currentNode->setAttributeNS($namespaceURI, $qualifiedName, $value); 3462 } 3463 3464 //and add xmlns attributes 3465 if ($this->waitingForElementToDeclareNamespaces) { 3466 //map namespace declarations to element 3467 foreach ($this->tempNamespaceURIMap as $key => $value) { 3468 $currentNode->namespaceURIMap[$key] = $value ; 3469 3470 //xmlns prefix has prefix: http://www.w3.org/2000/xmlns/ 3471 $currentNode->setAttributeNS(DOMIT_XMLNS_NAMESPACE, ('xmlns:' . $value), $key); 3472 } 3473 3474 //reset variables 3475 $this->tempNamespaceURIMap = array(); 3476 $this->waitingForElementToDeclareNamespaces = false; 3477 } 3478 3479 $this->lastChild =& $currentNode; 3480 } //startElementNS 3481 3482 3483 /** 3484 * Catches an end element event and processes the data 3485 * @param Object A reference to the current SAX parser 3486 * @param string The tag name of the current element 3487 */ 3488 function endElement(&$parser, $name) { 3489 if ($this->inTextNode) { 3490 $this->dumpTextNode(); 3491 } 3492 3493 $this->lastChild =& $this->lastChild->parentNode; 3494 } //endElement 3495 3496 /** 3497 * Catches a data event and processes the text 3498 * @param Object A reference to the current SAX parser 3499 * @param string The current text data 3500 */ 3501 function dataElement(&$parser, $data) { 3502 if (!$this->inCDATASection) { 3503 $this->inTextNode = true; 3504 } 3505 3506 $this->parseContainer .= $data; 3507 } //dataElement 3508 3509 /** 3510 * Catches a CDATA Section event and processes the text 3511 * @param Object A reference to the current SAX parser 3512 * @param string The current text data 3513 */ 3514 function cdataElement(&$parser, $data) { 3515 $currentNode =& $this->xmlDoc->createCDATASection($data); 3516 3517 $this->lastChild->appendChild($currentNode); 3518 } //cdataElement 3519 3520 /** 3521 * Catches a default data event and processes the data 3522 * @param Object A reference to the current SAX parser 3523 * @param string The current data 3524 */ 3525 function defaultDataElement(&$parser, $data) { 3526 if ((strlen($data) > 2) && ($this->parseItem == '')){ 3527 $pre = strtoupper(substr($data, 0, 3)); 3528 3529 switch ($pre) { 3530 case '<?X': //xml declaration 3531 $this->processingInstructionElement($parser, 'xml', substr($data, 6, (strlen($data) - 6 - 2))); 3532 break; 3533 case '<!E': //dtd entity 3534 $this->xmlDoc->doctype .= "\n " . $data; 3535 break; 3536 case '<![': //cdata section coming 3537 if ($this->preserveCDATA) { 3538 $this->inCDATASection = true; 3539 } 3540 break; 3541 case '<!-': //comment 3542 $currentNode = $this->commentElement($this, substr($data, 4, (strlen($data) - 7))); 3543 break; 3544 case '<!D': //doctype 3545 $this->parseItem = 'doctype'; 3546 $this->parseContainer = $data; 3547 break; 3548 case ']]>': //cdata end tag 3549 if ($this->preserveCDATA) { 3550 $currentNode =& $this->xmlDoc->createCDATASection($this->parseContainer); 3551 $this->lastChild->appendChild($currentNode); 3552 $this->inCDATASection = false; 3553 $this->parseContainer = ''; 3554 } 3555 else { 3556 $this->dumpTextNode(); 3557 } 3558 break; 3559 } 3560 } 3561 else { 3562 switch ($this->parseItem) { 3563 case 'doctype': 3564 $this->parseContainer .= $data; 3565 3566 if ($data == '>') { 3567 $this->doctypeElement($parser, $this->parseContainer); 3568 $this->parseContainer = ''; 3569 $this->parseItem = ''; 3570 } 3571 else if ($data == '[') { 3572 $this->parseItem = 'doctype_inline'; 3573 } 3574 break; 3575 3576 case 'doctype_inline': 3577 $this->parseContainer .= $data; 3578 3579 if ($data == ']') { 3580 $this->parseItem = 'doctype'; 3581 } 3582 else if ($data{(strlen($data) - 1)} == '>') { 3583 $this->parseContainer .= "\n "; 3584 } 3585 break; 3586 } 3587 } 3588 } //defaultDataElement 3589 3590 /** 3591 * Catches a doctype event and processes the data 3592 * @param Object A reference to the current SAX parser 3593 * @param string The current data 3594 */ 3595 function doctypeElement(&$parser, $data) { 3596 $start = strpos($data, '<!DOCTYPE'); 3597 $name = trim(substr($data, $start)); 3598 $end = strpos($name, ' '); 3599 $name = substr($name, 0, $end); 3600 3601 $currentNode = new DOMIT_DocumentType($name, $data); 3602 $currentNode->ownerDocument =& $this->xmlDoc; 3603 3604 $this->lastChild->appendChild($currentNode); 3605 $this->xmlDoc->doctype =& $currentNode; 3606 } //doctypeElement 3607 3608 /** 3609 * Catches a notation node event and processes the data 3610 * @param Object A reference to the current SAX parser 3611 * @param string The current notation data 3612 */ 3613 function notationElement(&$parser, $data) { 3614 //add to doctype string 3615 if (($this->parseItem == 'doctype_inline') || ($this->parseItem == 'doctype')) { 3616 $this->parseContainer .= $data; 3617 } 3618 } //notationElement 3619 3620 /** 3621 * Catches a comment node event and processes the data 3622 * @param Object A reference to the current SAX parser 3623 * @param string The comment data 3624 */ 3625 function commentElement(&$parser, $data) { 3626 if ($this->inTextNode) { 3627 $this->dumpTextNode(); 3628 } 3629 3630 $currentNode =& $this->xmlDoc->createComment($data); 3631 $this->lastChild->appendChild($currentNode); 3632 } //commentElement 3633 3634 /** 3635 * Catches a processing instruction node event and processes the data 3636 * @param Object A reference to the current SAX parser 3637 * @param string The target of the processing instruction data 3638 * @param string The processing instruction data 3639 */ 3640 function processingInstructionElement(&$parser, $target, $data) { 3641 if ($this->inTextNode) { 3642 $this->dumpTextNode(); 3643 } 3644 3645 $currentNode =& $this->xmlDoc->createProcessingInstruction($target, $data); 3646 $this->lastChild->appendChild($currentNode); 3647 3648 if (strtolower($target) == 'xml') { 3649 $this->xmlDoc->xmlDeclaration =& $currentNode; 3650 } 3651 } //processingInstructionElement 3652 3653 /** 3654 * Catches a start namespace declaration event and processes the data 3655 * @param Object A reference to the current SAX parser 3656 * @param string The namespace prefix 3657 * @param string The namespace uri 3658 */ 3659 function startNamespaceDeclaration(&$parser, $prefix, $uri) { 3660 //make uri lower case because Expat forces it to upper case for some reason 3661 $this->xmlDoc->namespaceURIMap[strtolower($uri)] = $prefix; 3662 3663 //set up a switch so when the target element arrives, namespaces can be mapped to it 3664 $this->waitingForElementToDeclareNamespaces = true; 3665 $this->tempNamespaceURIMap[strtolower($uri)] = $prefix; 3666 } //startNamespaceDeclaration 3667 3668 /** 3669 * Catches an end namespace declaration event 3670 * @param Object A reference to the current SAX parser 3671 * @param string The namespace prefix 3672 */ 3673 function endNamespaceDeclaration(&$parser, $prefix) { 3674 //do nothing; could remove from map, but would hardly be optimal 3675 } //endNamespaceDeclaration 3676 3677 } //DOMIT_Parser 3678 3679 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 14:43:32 2007 | par Balluche grâce à PHPXref 0.7 |
|