[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 3 // 4 // +----------------------------------------------------------------------+ 5 // | <phpXML/> version 1.0 | 6 // | Copyright (c) 2001 Michael P. Mehl. All rights reserved. | 7 // +----------------------------------------------------------------------+ 8 // | Latest releases are available at http://phpxml.org/. For feedback or | 9 // | bug reports, please contact the author at mpm@phpxml.org. Thanks! | 10 // +----------------------------------------------------------------------+ 11 // | The contents of this file are subject to the Mozilla Public License | 12 // | Version 1.1 (the "License"); you may not use this file except in | 13 // | compliance with the License. You may obtain a copy of the License at | 14 // | http://www.mozilla.org/MPL/ | 15 // | | 16 // | Software distributed under the License is distributed on an "AS IS" | 17 // | basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | 18 // | the License for the specific language governing rights and | 19 // | limitations under the License. | 20 // | | 21 // | The Original Code is <phpXML/>. | 22 // | | 23 // | The Initial Developer of the Original Code is Michael P. Mehl. | 24 // | Portions created by Michael P. Mehl are Copyright (C) 2001 Michael | 25 // | P. Mehl. All Rights Reserved. | 26 // +----------------------------------------------------------------------+ 27 // | Authors: | 28 // | Michael P. Mehl <mpm@phpxml.org> | 29 // +----------------------------------------------------------------------+ 30 // 31 32 /** 33 * Class for accessing XML data through the XPath language. 34 * 35 * This class offers methods for accessing the nodes of a XML document using 36 * the XPath language. You can add or remove nodes, set or modify their 37 * content and their attributes. No additional PHP extensions like DOM XML 38 * or something similar are required to use these features. 39 * 40 * @link http://www.phpxml.org/ Latest release of this class 41 * @link http://www.w3.org/TR/xpath W3C XPath Recommendation 42 * @copyright Copyright (c) 2001 Michael P. Mehl. All rights reserved. 43 * @author Michael P. Mehl <mpm@phpxml.org> 44 * @version 1.0 (2001-03-08) 45 * @access public 46 */ 47 48 class XML 49 { 50 /** 51 * List of all document nodes. 52 * 53 * This array contains a list of all document nodes saved as an 54 * associative array. 55 * 56 * @access private 57 * @var array 58 */ 59 var $nodes = array(); 60 61 /** 62 * List of document node IDs. 63 * 64 * This array contains a list of all IDs of all document nodes that 65 * are used for counting when adding a new node. 66 * 67 * @access private 68 * @var array 69 */ 70 var $ids = array(); 71 72 /** 73 * Current document path. 74 * 75 * This variable saves the current path while parsing a XML file and adding 76 * the nodes being read from the file. 77 * 78 * @access private 79 * @var string 80 */ 81 var $path = ""; 82 83 /** 84 * Current document position. 85 * 86 * This variable counts the current document position while parsing a XML 87 * file and adding the nodes being read from the file. 88 * 89 * @access private 90 * @var int 91 */ 92 var $position = 0; 93 94 /** 95 * Path of the document root. 96 * 97 * This string contains the full path to the node that acts as the root 98 * node of the whole document. 99 * 100 * @access private 101 * @var string 102 */ 103 var $root = ""; 104 105 /** 106 * Current XPath expression. 107 * 108 * This string contains the full XPath expression being parsed currently. 109 * 110 * @access private 111 * @var string 112 */ 113 var $xpath = ""; 114 115 /** 116 * List of entities to be converted. 117 * 118 * This array contains a list of entities to be converted when an XPath 119 * expression is evaluated. 120 * 121 * @access private 122 * @var array 123 */ 124 var $entities = array ( "&" => "&", "<" => "<", ">" => ">", 125 "'" => "&apos", '"' => """ ); 126 127 /** 128 * List of supported XPath axes. 129 * 130 * This array contains a list of all valid axes that can be evaluated in an 131 * XPath expression. 132 * 133 * @access private 134 * @var array 135 */ 136 var $axes = array ( "child", "descendant", "parent", "ancestor", 137 "following-sibling", "preceding-sibling", "following", "preceding", 138 "attribute", "namespace", "self", "descendant-or-self", 139 "ancestor-or-self" ); 140 141 /** 142 * List of supported XPath functions. 143 * 144 * This array contains a list of all valid functions that can be evaluated 145 * in an XPath expression. 146 * 147 * @access private 148 * @var array 149 */ 150 var $functions = array ( "last", "position", "count", "id", "name", 151 "string", "concat", "starts-with", "contains", "substring-before", 152 "substring-after", "substring", "string-length", "translate", 153 "boolean", "not", "true", "false", "lang", "number", "sum", "floor", 154 "ceiling", "round", "text" ); 155 156 /** 157 * List of supported XPath operators. 158 * 159 * This array contains a list of all valid operators that can be evaluated 160 * in a predicate of an XPath expression. The list is ordered by the 161 * precedence of the operators (lowest precedence first). 162 * 163 * @access private 164 * @var array 165 */ 166 var $operators = array( " or ", " and ", "=", "!=", "<=", "<", ">=", ">", 167 "+", "-", "*", " div ", " mod " ); 168 169 /** 170 * Constructor of the class. 171 * 172 * This constructor initializes the class and, when a filename is given, 173 * tries to read and parse the given file. 174 * 175 * @access public 176 * @author Michael P. Mehl <mpm@phpxml.org> 177 * @param string $file Path and name of the file to read and parsed. 178 * @see load_file() 179 */ 180 function XML ( $file = "" ) 181 { 182 // Check whether a file was given. 183 if ( !empty($file) ) 184 { 185 // Load the XML file. 186 $this->load_file($file); 187 } 188 } 189 190 /** 191 * Reads a file and parses the XML data. 192 * 193 * This method reads the content of a XML file, tries to parse its 194 * content and upon success stores the information retrieved from 195 * the file into an array. 196 * 197 * @access public 198 * @author Michael P. Mehl <mpm@phpxml.org> 199 * @param string $file Path and name of the file to be read and parsed. 200 * @see handle_start_element(), handle_end_element(), 201 * handle_character_data() 202 */ 203 function load_file ( $file ) 204 { 205 // Check whether the file exists and is readable. 206 if ( file_exists($file) && is_readable($file) ) 207 { 208 // Read the content of the file. 209 $content = implode("", file($file)); 210 211 // Check whether content has been read. 212 if ( !empty($content) ) 213 { 214 // Create an XML parser. 215 $parser = xml_parser_create(); 216 217 // Set the options for parsing the XML data. 218 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 219 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 220 221 // Set the object for the parser. 222 xml_set_object($parser, &$this); 223 224 // Set the element handlers for the parser. 225 xml_set_element_handler($parser, "handle_start_element", 226 "handle_end_element"); 227 xml_set_character_data_handler($parser, 228 "handle_character_data"); 229 230 // Parse the XML file. 231 if ( !xml_parse($parser, $content, true) ) 232 { 233 // Display an error message. 234 $this->display_error("XML error in file %s, line %d: %s", 235 $file, xml_get_current_line_number($parser), 236 xml_error_string(xml_get_error_code($parser))); 237 } 238 239 // Free the parser. 240 xml_parser_free($parser); 241 } 242 } 243 else 244 { 245 // Display an error message. 246 $this->display_error("File %s could not be found or read.", $file); 247 } 248 } 249 250 /** 251 * Generates a XML file with the content of the current document. 252 * 253 * This method creates a string containing the XML data being read 254 * and modified by this class before. This string can be used to save 255 * a modified document back to a file or doing other nice things with 256 * it. 257 * 258 * @access public 259 * @author Michael P. Mehl <mpm@phpxml.org> 260 * @param array $highlight Array containing a list of full document 261 * paths of nodes to be highlighted by <font>...</font> tags 262 * in the generated XML string. 263 * @param string $root While doing a recursion with this method, this 264 * parameter is used for internal purpose. 265 * @param int $level While doing a recursion with this method, this 266 * parameter is used for internal purpose. 267 * @return string The returned string contains well-formed XML data 268 * representing the content of this document. 269 * @see load_file(), evaluate(), get_content() 270 */ 271 function get_file ( $highlight = array(), $root = "", $level = 0 ) 272 { 273 // Create a string to save the generated XML data. 274 $xml = ""; 275 276 // Create two strings containing the tags for highlighting a node. 277 $highlight_start = "<font color=\"#FF0000\"><b>"; 278 $highlight_end = "</b></font>"; 279 280 // Generate a string to be displayed before the tags. 281 $before = ""; 282 283 // Calculate the amount of whitespaces to display. 284 for ( $i = 0; $i < ( $level * 2 ); $i++ ) 285 { 286 // Add a whitespaces to the string. 287 $before .= " "; 288 } 289 290 // Check whether a root node is given. 291 if ( empty($root) ) 292 { 293 // Set it to the document root. 294 $root = $this->root; 295 } 296 297 // Check whether the node is selected. 298 $selected = in_array($root, $highlight); 299 300 // Now add the whitespaces to the XML data. 301 $xml .= $before; 302 303 // Check whether the node is selected. 304 if ( $selected ) 305 { 306 // Add the highlight code to the XML data. 307 $xml .= $highlight_start; 308 } 309 310 // Now open the tag. 311 $xml .= "<".$this->nodes[$root]["name"]; 312 313 // Check whether there are attributes for this node. 314 if ( count($this->nodes[$root]["attributes"]) > 0 ) 315 { 316 // Run through all attributes. 317 foreach ( $this->nodes[$root]["attributes"] as $key => $value ) 318 { 319 // Check whether this attribute is highlighted. 320 if ( in_array($root."/attribute::".$key, $highlight) ) 321 { 322 // Add the highlight code to the XML data. 323 $xml .= $highlight_start; 324 } 325 326 // Add the attribute to the XML data. 327 $xml .= " ".$key."=\"".trim(stripslashes($value))."\""; 328 329 // Check whether this attribute is highlighted. 330 if ( in_array($root."/attribute::".$key, $highlight) ) 331 { 332 // Add the highlight code to the XML data. 333 $xml .= $highlight_end; 334 } 335 } 336 } 337 338 // Check whether the node contains character data or has children. 339 if ( empty($this->nodes[$root]["text"]) && 340 !isset($this->nodes[$root]["children"]) ) 341 { 342 // Add the end to the tag. 343 $xml .= "/"; 344 } 345 346 // Close the tag. 347 $xml .= ">\n"; 348 349 // Check whether the node is selected. 350 if ( $selected ) 351 { 352 // Add the highlight code to the XML data. 353 $xml .= $highlight_end; 354 } 355 356 // Check whether the node contains character data. 357 if ( !empty($this->nodes[$root]["text"]) ) 358 { 359 // Add the character data to the XML data. 360 $xml .= $before." ".$this->nodes[$root]["text"]."\n"; 361 } 362 363 // Check whether the node has children. 364 if ( isset($this->nodes[$root]["children"]) ) 365 { 366 // Run through all children with different names. 367 foreach ( $this->nodes[$root]["children"] as $child => $pos ) 368 { 369 // Run through all children with the same name. 370 for ( $i = 1; $i <= $pos; $i++ ) 371 { 372 // Generate the full path of the child. 373 $fullchild = $root."/".$child."[".$i."]"; 374 375 // Add the child's XML data to the existing data. 376 $xml .= $this->get_file($highlight, $fullchild, 377 $level + 1); 378 } 379 } 380 } 381 382 // Check whether there are attributes for this node. 383 if ( !empty($this->nodes[$root]["text"]) || 384 isset($this->nodes[$root]["children"]) ) 385 { 386 // Add the whitespaces to the XML data. 387 $xml .= $before; 388 389 // Check whether the node is selected. 390 if ( $selected ) 391 { 392 // Add the highlight code to the XML data. 393 $xml .= $highlight_start; 394 } 395 396 // Add the closing tag. 397 $xml .= "</".$this->nodes[$root]["name"].">"; 398 399 // Check whether the node is selected. 400 if ( $selected ) 401 { 402 // Add the highlight code to the XML data. 403 $xml .= $highlight_end; 404 } 405 406 // Add a linebreak. 407 $xml .= "\n"; 408 } 409 410 // Return the XML data. 411 return $xml; 412 } 413 414 /** 415 * Adds a new node to the XML document. 416 * 417 * This method adds a new node to the tree of nodes of the XML document 418 * being handled by this class. The new node is created according to the 419 * parameters passed to this method. 420 * 421 * @access public 422 * @author Michael P. Mehl <mpm@phpxml.org> 423 * @param string $content Full path of the parent, to which the new 424 * node should be added as a child. 425 * @param string $name Name of the new node. 426 * @return string The string returned by this method will contain the 427 * full document path of the created node. 428 * @see remove_node(), evaluate() 429 */ 430 function add_node ( $context, $name ) 431 { 432 // Check whether a name for this element is already set. 433 if ( empty($this->root) ) 434 { 435 // Use this tag as the root element. 436 $this->root = "/".$name."[1]"; 437 } 438 439 // Calculate the full path for this element. 440 $path = $context."/".$name; 441 442 // Set the relative context and the position. 443 $position = ++$this->ids[$path]; 444 $relative = $name."[".$position."]"; 445 446 // Calculate the full path. 447 $fullpath = $context."/".$relative; 448 449 // Calculate the context position, which is the position of this 450 // element within elements of the same name in the parent node. 451 $this->nodes[$fullpath]["context-position"] = $position; 452 453 // Calculate the position for the following and preceding axis 454 // detection. 455 $this->nodes[$fullpath]["document-position"] = 456 $this->nodes[$context]["document-position"] + 1; 457 458 // Save the information about the node. 459 $this->nodes[$fullpath]["name"] = $name; 460 $this->nodes[$fullpath]["text"] = ""; 461 $this->nodes[$fullpath]["parent"] = $context; 462 463 // Add this element to the element count array. 464 if ( !$this->nodes[$context]["children"][$name] ) 465 { 466 // Set the default name. 467 $this->nodes[$context]["children"][$name] = 1; 468 } 469 else 470 { 471 // Calculate the name. 472 $this->nodes[$context]["children"][$name] = 473 $this->nodes[$context]["children"][$name] + 1; 474 } 475 476 // Return the path of the new node. 477 return $fullpath; 478 } 479 480 /** 481 * Removes a node from the XML document. 482 * 483 * This method removes a node from the tree of nodes of the XML document. 484 * If the node is a document node, all children of the node and its 485 * character data will be removed. If the node is an attribute node, 486 * only this attribute will be removed, the node to which the attribute 487 * belongs as well as its children will remain unmodified. 488 * 489 * @access public 490 * @author Michael P. Mehl <mpm@phpxml.org> 491 * @param string $node Full path of the node to be removed. 492 * @see add_node(), evaluate() 493 */ 494 function remove_node ( $node ) 495 { 496 // Check whether the node is an attribute node. 497 if ( ereg("/attribute::", $node) ) 498 { 499 // Get the path to the attribute node's parent. 500 $parent = $this->prestr($node, "/attribute::"); 501 502 // Get the name of the attribute. 503 $attribute = $this->afterstr($node, "/attribute::"); 504 505 // Check whether the attribute exists. 506 if ( isset($this->nodes[$parent]["attributes"][$attribute]) ) 507 { 508 // Create a new array. 509 $new = array(); 510 511 // Run through the existing attributes. 512 foreach ( $this->nodes[$parent]["attributes"] 513 as $key => $value ) 514 { 515 // Check whether it's the attribute to remove. 516 if ( $key != $attribute ) 517 { 518 // Add it to the new array again. 519 $new[$key] = $value; 520 } 521 } 522 523 // Save the new attributes. 524 $this->nodes[$parent]["attributes"] = $new; 525 } 526 } 527 else 528 { 529 // Create an associative array, which contains information about 530 // all nodes that required to be renamed. 531 $rename = array(); 532 533 // Get the name, the parent and the siblings of current node. 534 $name = $this->nodes[$node]["name"]; 535 $parent = $this->nodes[$node]["parent"]; 536 $siblings = $this->nodes[$parent]["children"][$name]; 537 538 // Decrease the number of children. 539 $this->nodes[$parent]["children"][$name]--; 540 541 // Create a counter for renumbering the siblings. 542 $counter = 1; 543 544 // Now run through the siblings. 545 for ( $i = 1; $i <= $siblings; $i++ ) 546 { 547 // Create the name of the sibling. 548 $sibling = $parent."/".$name."[".$i."]"; 549 550 // Check whether it's the name of the current node. 551 if ( $sibling != $node ) 552 { 553 // Create the new name for the sibling. 554 $new = $parent."/".$name."[".$counter."]"; 555 556 // Increase the counter. 557 $counter++; 558 559 // Add the old and the new name to the list of nodes 560 // to be renamed. 561 $rename[$sibling] = $new; 562 } 563 } 564 565 // Create an array for saving the new node-list. 566 $nodes = array(); 567 568 // Now run through through the existing nodes. 569 foreach ( $this->nodes as $name => $values ) 570 { 571 // Check the position of the path of the node to be deleted 572 // in the path of the current node. 573 $position = strpos($name, $node); 574 575 // Check whether it's not the node to be deleted. 576 if ( $position === false ) 577 { 578 // Run through the array of nodes to be renamed. 579 foreach ( $rename as $old => $new ) 580 { 581 // Check whether this node and it's parent requires to 582 // be renamed. 583 $name = str_replace($old, $new, $name); 584 $values["parent"] = str_replace($old, $new, 585 $values["parent"]); 586 } 587 588 // Add the node to the list of nodes. 589 $nodes[$name] = $values; 590 } 591 } 592 593 // Save the new array of nodes. 594 $this->nodes = $nodes; 595 } 596 } 597 598 /** 599 * Add content to a node. 600 * 601 * This method adds content to a node. If it's an attribute node, then 602 * the value of the attribute will be set, otherwise the character data of 603 * the node will be set. The content is appended to existing content, 604 * so nothing will be overwritten. 605 * 606 * @access public 607 * @author Michael P. Mehl <mpm@phpxml.org> 608 * @param string $path Full document path of the node. 609 * @param string $value String containing the content to be added. 610 * @see get_content(), evaluate() 611 */ 612 function add_content ( $path, $value ) 613 { 614 // Check whether it's an attribute node. 615 if ( ereg("/attribute::", $path) ) 616 { 617 // Get the path to the attribute node's parent. 618 $parent = $this->prestr($path, "/attribute::"); 619 620 // Get the parent node. 621 $parent = $this->nodes[$parent]; 622 623 // Get the name of the attribute. 624 $attribute = $this->afterstr($path, "/attribute::"); 625 626 // Set the attribute. 627 $parent["attributes"][$attribute] .= $value; 628 } 629 else 630 { 631 // Set the character data of the node. 632 $this->nodes[$path]["text"] .= $value; 633 } 634 } 635 636 /** 637 * Set the content of a node. 638 * 639 * This method sets the content of a node. If it's an attribute node, then 640 * the value of the attribute will be set, otherwise the character data of 641 * the node will be set. Existing content will be overwritten. 642 * 643 * @access public 644 * @author Michael P. Mehl <mpm@phpxml.org> 645 * @param string $path Full document path of the node. 646 * @param string $value String containing the content to be set. 647 * @see get_content(), evaluate() 648 */ 649 function set_content ( $path, $value ) 650 { 651 // Check whether it's an attribute node. 652 if ( ereg("/attribute::", $path) ) 653 { 654 // Get the path to the attribute node's parent. 655 $parent = $this->prestr($path, "/attribute::"); 656 657 // Get the parent node. 658 $parent = $this->nodes[$parent]; 659 660 // Get the name of the attribute. 661 $attribute = $this->afterstr($path, "/attribute::"); 662 663 // Set the attribute. 664 $parent["attributes"][$attribute] = $value; 665 } 666 else 667 { 668 // Set the character data of the node. 669 $this->nodes[$path]["text"] = $value; 670 } 671 } 672 673 /** 674 * Retrieves the content of a node. 675 * 676 * This method retrieves the content of a node. If it's an attribute 677 * node, then the value of the attribute will be retrieved, otherwise 678 * it'll be the character data of the node. 679 * 680 * @access public 681 * @author Michael P. Mehl <mpm@phpxml.org> 682 * @param string $path Full document path of the node, from which the 683 * content should be retrieved. 684 * @return string The returned string contains either the value or the 685 * character data of the node. 686 * @see set_content(), evaluate() 687 */ 688 function get_content ( $path ) 689 { 690 // Check whether it's an attribute node. 691 if ( ereg("/attribute::", $path) ) 692 { 693 // Get the path to the attribute node's parent. 694 $parent = $this->prestr($path, "/attribute::"); 695 696 // Get the parent node. 697 $parent = $this->nodes[$parent]; 698 699 // Get the name of the attribute. 700 $attribute = $this->afterstr($path, "/attribute::"); 701 702 // Get the attribute. 703 $attribute = $parent["attributes"][$attribute]; 704 705 // Return the value of the attribute. 706 return $attribute; 707 } 708 else 709 { 710 // Return the cdata of the node. 711 return stripslashes($this->nodes[$path]["text"]); 712 } 713 } 714 715 /** 716 * Add attributes to a node. 717 * 718 * This method adds attributes to a node. Existing attributes will not be 719 * overwritten. 720 * 721 * @access public 722 * @author Michael P. Mehl <mpm@phpxml.org> 723 * @param string $path Full document path of the node, the attributes 724 * should be added to. 725 * @param array $attributes Associative array containing the new 726 * attributes for the node. 727 * @see set_content(), get_content() 728 */ 729 function add_attributes ( $path, $attributes ) 730 { 731 // Add the attributes to the node. 732 $this->nodes[$path]["attributes"] = array_merge($attributes, 733 $this->nodes[$path]["attributes"]); 734 } 735 736 /** 737 * Sets the attributes of a node. 738 * 739 * This method sets the attributes of a node and overwrites all existing 740 * attributes by doing this. 741 * 742 * @access public 743 * @author Michael P. Mehl <mpm@phpxml.org> 744 * @param string $path Full document path of the node, the attributes 745 * of which should be set. 746 * @param array $attributes Associative array containing the new 747 * attributes for the node. 748 * @see set_content(), get_content() 749 */ 750 function set_attributes ( $path, $attributes ) 751 { 752 // Set the attributes of the node. 753 $this->nodes[$path]["attributes"] = $attributes; 754 } 755 756 /** 757 * Retrieves a list of all attributes of a node. 758 * 759 * This method retrieves a list of all attributes of the node specified in 760 * the argument. 761 * 762 * @access public 763 * @author Michael P. Mehl <mpm@phpxml.org> 764 * @param string $path Full document path of the node, from which the 765 * list of attributes should be retrieved. 766 * @return array The returned associative array contains the all 767 * attributes of the specified node. 768 * @see get_content(), $nodes, $ids 769 */ 770 function get_attributes ( $path ) 771 { 772 // Return the attributes of the node. 773 return $this->nodes[$path]["attributes"]; 774 } 775 776 /** 777 * Retrieves the name of a document node. 778 * 779 * This method retrieves the name of document node specified in the 780 * argument. 781 * 782 * @access public 783 * @author Michael P. Mehl <mpm@phpxml.org> 784 * @param string $path Full document path of the node, from which the 785 * name should be retrieved. 786 * @return string The returned array contains the name of the specified 787 * node. 788 * @see get_content(), $nodes, $ids 789 */ 790 function get_name ( $path ) 791 { 792 // Return the name of the node. 793 return $this->nodes[$path]["name"]; 794 } 795 796 /** 797 * Evaluates an XPath expression. 798 * 799 * This method tries to evaluate an XPath expression by parsing it. A 800 * XML document has to be read before this method is able to work. 801 * 802 * @access public 803 * @author Michael P. Mehl <mpm@phpxml.org> 804 * @param string $path XPath expression to be evaluated. 805 * @param string $context Full path of a document node, starting 806 * from which the XPath expression should be evaluated. 807 * @return array The returned array contains a list of the full 808 * document paths of all nodes that match the evaluated 809 * XPath expression. 810 * @see $nodes, $ids 811 */ 812 function evaluate ( $path, $context = "" ) 813 { 814 // Remove slashes and quote signs. 815 $path = stripslashes($path); 816 $path = str_replace("\"", "", $path); 817 $path = str_replace("'", "", $path); 818 819 // Split the paths into different paths. 820 $paths = $this->split_paths($path); 821 822 // Create an empty set to save the result. 823 $result = array(); 824 825 // Run through all paths. 826 foreach ( $paths as $path ) 827 { 828 // Trim the path. 829 $path = trim($path); 830 831 // Save the current path. 832 $this->xpath = $path; 833 834 // Convert all entities. 835 $path = strtr($path, array_flip($this->entities)); 836 837 // Split the path at every slash. 838 $steps = $this->split_steps($path); 839 840 // Check whether the first element is empty. 841 if ( empty($steps[0]) ) 842 { 843 // Remove the first and empty element. 844 array_shift($steps); 845 } 846 847 // Start to evaluate the steps. 848 $nodes = $this->evaluate_step($context, $steps); 849 850 // Remove duplicated nodes. 851 $nodes = array_unique($nodes); 852 853 // Add the nodes to the result set. 854 $result = array_merge($result, $nodes); 855 } 856 857 // Return the result. 858 return $result; 859 } 860 861 /** 862 * Handles opening XML tags while parsing. 863 * 864 * While parsing a XML document for each opening tag this method is 865 * called. It'll add the tag found to the tree of document nodes. 866 * 867 * @access private 868 * @author Michael P. Mehl <mpm@phpxml.org> 869 * @param int $parser Handler for accessing the current XML parser. 870 * @param string $name Name of the opening tag found in the document. 871 * @param array $attributes Associative array containing a list of 872 * all attributes of the tag found in the document. 873 * @see handle_end_element(), handle_character_data(), $nodes, $ids 874 */ 875 function handle_start_element ( $parser, $name, $attributes ) 876 { 877 // Add a node. 878 $this->path = $this->add_node($this->path, $name); 879 880 // Set the attributes. 881 $this->set_attributes($this->path, $attributes); 882 } 883 884 /** 885 * Handles closing XML tags while parsing. 886 * 887 * While parsing a XML document for each closing tag this method is 888 * called. 889 * 890 * @access private 891 * @author Michael P. Mehl <mpm@phpxml.org> 892 * @param int $parser Handler for accessing the current XML parser. 893 * @param string $name Name of the closing tag found in the document. 894 * @see handle_start_element(), handle_character_data(), $nodes, $ids 895 */ 896 function handle_end_element ( $parser, $name ) 897 { 898 // Jump back to the parent element. 899 $this->path = substr($this->path, 0, strrpos($this->path, "/")); 900 } 901 902 /** 903 * Handles character data while parsing. 904 * 905 * While parsing a XML document for each character data this method 906 * is called. It'll add the character data to the document tree. 907 * 908 * @access private 909 * @author Michael P. Mehl <mpm@phpxml.org> 910 * @param int $parser Handler for accessing the current XML parser. 911 * @param string $text Character data found in the document. 912 * @see handle_start_element(), handle_end_element(), $nodes, $ids 913 */ 914 function handle_character_data ( $parser, $text ) 915 { 916 // Replace entities. 917 $text = strtr($text, $this->entities); 918 919 // Save the text. 920 $this->add_content($this->path, addslashes(trim($text))); 921 } 922 923 /** 924 * Splits an XPath expression into its different expressions. 925 * 926 * This method splits an XPath expression. Each expression can consists of 927 * list of expression being separated from each other by a | character. 928 * 929 * @access private 930 * @author Michael P. Mehl <mpm@phpxml.org> 931 * @param string $expression The complete expression to be splitted 932 * into its different expressions. 933 * @return array The array returned from this method contains a list 934 * of all expressions found in the expression passed to this 935 * method as a parameter. 936 * @see evalute() 937 */ 938 function split_paths ( $expression ) 939 { 940 // Create an empty array. 941 $paths = array(); 942 943 // Save the position of the slash. 944 $position = -1; 945 946 // Run through the expression. 947 do 948 { 949 // Search for a slash. 950 $position = $this->search_string($expression, "|"); 951 952 // Check whether a | was found. 953 if ( $position >= 0 ) 954 { 955 // Get the left part of the expression. 956 $left = substr($expression, 0, $position); 957 $right = substr($expression, $position + 1); 958 959 // Add the left value to the steps. 960 $paths[] = $left; 961 962 // Reduce the expression to the right part. 963 $expression = $right; 964 } 965 } 966 while ( $position > -1 ); 967 968 // Add the remaing expression to the list of steps. 969 $paths[] = $expression; 970 971 // Return the steps. 972 return $paths; 973 } 974 975 /** 976 * Splits an XPath expression into its different steps. 977 * 978 * This method splits an XPath expression. Each expression can consists of 979 * list of steps being separated from each other by a / character. 980 * 981 * @access private 982 * @author Michael P. Mehl <mpm@phpxml.org> 983 * @param string $expression The complete expression to be splitted 984 * into its different steps. 985 * @return array The array returned from this method contains a list 986 * of all steps found in the expression passed to this 987 * method as a parameter. 988 * @see evalute() 989 */ 990 function split_steps ( $expression ) 991 { 992 // Create an empty array. 993 $steps = array(); 994 995 // Replace a double slashes, because they'll cause problems otherwise. 996 $expression = str_replace("//@", "/descendant::*/@", $expression); 997 $expression = str_replace("//", "/descendant::", $expression); 998 999 // Save the position of the slash. 1000 $position = -1; 1001 1002 // Run through the expression. 1003 do 1004 { 1005 // Search for a slash. 1006 $position = $this->search_string($expression, "/"); 1007 1008 // Check whether a slash was found. 1009 if ( $position >= 0 ) 1010 { 1011 // Get the left part of the expression. 1012 $left = substr($expression, 0, $position); 1013 $right = substr($expression, $position + 1); 1014 1015 // Add the left value to the steps. 1016 $steps[] = $left; 1017 1018 // Reduce the expression to the right part. 1019 $expression = $right; 1020 } 1021 } 1022 while ( $position > -1 ); 1023 1024 // Add the remaing expression to the list of steps. 1025 $steps[] = $expression; 1026 1027 // Return the steps. 1028 return $steps; 1029 } 1030 1031 /** 1032 * Retrieves axis information from an XPath expression step. 1033 * 1034 * This method tries to extract the name of the axis and its node-test 1035 * from a given step of an XPath expression at a given node. 1036 * 1037 * @access private 1038 * @author Michael P. Mehl <mpm@phpxml.org> 1039 * @param string $step String containing a step of an XPath expression. 1040 * @param string $node Full document path of the node on which the 1041 * step is executed. 1042 * @return array This method returns an array containing information 1043 * about the axis found in the step. 1044 * @see evaluate_step() 1045 */ 1046 function get_axis ( $step, $node ) 1047 { 1048 // Create an array to save the axis information. 1049 $axis = array( 1050 "axis" => "", 1051 "node-test" => "", 1052 "predicate" => array() 1053 ); 1054 1055 // Check whether there are predicates. 1056 if ( ereg("\[", $step) ) 1057 { 1058 // Get the predicates. 1059 $predicates = substr($step, strpos($step, "[")); 1060 1061 // Reduce the step. 1062 $step = $this->prestr($step, "["); 1063 1064 // Try to split the predicates. 1065 $predicates = str_replace("][", "]|[", $predicates); 1066 $predicates = explode("|", $predicates); 1067 1068 // Run through all predicates. 1069 foreach ( $predicates as $predicate ) 1070 { 1071 // Remove the brackets. 1072 $predicate = substr($predicate, 1, strlen($predicate) - 2); 1073 1074 // Add the predicate to the list of predicates. 1075 $axis["predicate"][] = $predicate; 1076 } 1077 } 1078 1079 // Check whether the axis is given in plain text. 1080 if ( $this->search_string($step, "::") > -1 ) 1081 { 1082 // Split the step to extract axis and node-test. 1083 $axis["axis"] = $this->prestr($step, "::"); 1084 $axis["node-test"] = $this->afterstr($step, "::"); 1085 } 1086 else 1087 { 1088 // Check whether the step is empty. 1089 if ( empty($step) ) 1090 { 1091 // Set it to the default value. 1092 $step = "."; 1093 } 1094 1095 // Check whether is an abbreviated syntax. 1096 if ( $step == "*" ) 1097 { 1098 // Use the child axis and select all children. 1099 $axis["axis"] = "child"; 1100 $axis["node-test"] = "*"; 1101 } 1102 elseif ( ereg("\(", $step) ) 1103 { 1104 // Check whether it's a function. 1105 if ( $this->is_function($this->prestr($step, "(")) ) 1106 { 1107 // Get the position of the first bracket. 1108 $start = strpos($step, "("); 1109 $end = strpos($step, ")", $start); 1110 1111 // Get everything before, between and after the brackets. 1112 $before = substr($step, 0, $start); 1113 $between = substr($step, $start + 1, $end - $start - 1); 1114 $after = substr($step, $end + 1); 1115 1116 // Trim each string. 1117 $before = trim($before); 1118 $between = trim($between); 1119 $after = trim($after); 1120 1121 // Save the evaluated function. 1122 $axis["axis"] = "function"; 1123 $axis["node-test"] = $this->evaluate_function($before, 1124 $between, $node); 1125 } 1126 else 1127 { 1128 // Use the child axis and a function. 1129 $axis["axis"] = "child"; 1130 $axis["node-test"] = $step; 1131 } 1132 } 1133 elseif ( eregi("^@", $step) ) 1134 { 1135 // Use the attribute axis and select the attribute. 1136 $axis["axis"] = "attribute"; 1137 $axis["node-test"] = substr($step, 1); 1138 } 1139 elseif ( eregi("\]$", $step) ) 1140 { 1141 // Use the child axis and select a position. 1142 $axis["axis"] = "child"; 1143 $axis["node-test"] = substr($step, strpos($step, "[")); 1144 } 1145 elseif ( $step == "." ) 1146 { 1147 // Select the self axis. 1148 $axis["axis"] = "self"; 1149 $axis["node-test"] = "*"; 1150 } 1151 elseif ( $step == ".." ) 1152 { 1153 // Select the parent axis. 1154 $axis["axis"] = "parent"; 1155 $axis["node-test"] = "*"; 1156 } 1157 elseif ( ereg("^[a-zA-Z0-9\-_]+$", $step) ) 1158 { 1159 // Select the child axis and the child. 1160 $axis["axis"] = "child"; 1161 $axis["node-test"] = $step; 1162 } 1163 else 1164 { 1165 // Use the child axis and a name. 1166 $axis["axis"] = "child"; 1167 $axis["node-test"] = $step; 1168 } 1169 } 1170 1171 // Check whether it's a valid axis. 1172 if ( !in_array($axis["axis"], array_merge($this->axes, 1173 array("function"))) ) 1174 { 1175 // Display an error message. 1176 $this->display_error("While parsing an XPath expression, in ". 1177 "the step \"%s\" the invalid axis \"%s\" was found.", 1178 str_replace($step, "<b>".$step."</b>", $this->xpath),# 1179 $axis["axis"]); 1180 } 1181 1182 // Return the axis information. 1183 return $axis; 1184 } 1185 1186 /** 1187 * Looks for a string within another string. 1188 * 1189 * This method looks for a string within another string. Brackets in the 1190 * string the method is looking through will be respected, which means that 1191 * only if the string the method is looking for is located outside of 1192 * brackets, the search will be successful. 1193 * 1194 * @access private 1195 * @author Michael P. Mehl <mpm@phpxml.org> 1196 * @param string $term String in which the search shall take place. 1197 * @param string $expression String that should be searched. 1198 * @return int This method returns -1 if no string was found, otherwise 1199 * the offset at which the string was found. 1200 * @see evaluate_step() 1201 */ 1202 function search_string ( $term, $expression ) 1203 { 1204 // Create a new counter for the brackets. 1205 $brackets = 0; 1206 1207 // Run through the string. 1208 for ( $i = 0; $i < strlen($term); $i++ ) 1209 { 1210 // Get the character at the position of the string. 1211 $character = substr($term, $i, 1); 1212 1213 // Check whether it's a breacket. 1214 if ( ( $character == "(" ) || ( $character == "[" ) ) 1215 { 1216 // Increase the number of brackets. 1217 $brackets++; 1218 } 1219 elseif ( ( $character == ")" ) || ( $character == "]" ) ) 1220 { 1221 // Decrease the number of brackets. 1222 $brackets--; 1223 } 1224 elseif ( $brackets == 0 ) 1225 { 1226 // Check whether we can find the expression at this index. 1227 if ( substr($term, $i, strlen($expression)) == $expression ) 1228 { 1229 // Return the current index. 1230 return $i; 1231 } 1232 } 1233 } 1234 1235 // Check whether we had a valid number of brackets. 1236 if ( $brackets != 0 ) 1237 { 1238 // Display an error message. 1239 $this->display_error("While parsing an XPath expression, in the ". 1240 "predicate \"%s\", there was an invalid number of brackets.", 1241 str_replace($term, "<b>".$term."</b>", $this->xpath)); 1242 } 1243 1244 // Nothing was found. 1245 return (-1); 1246 } 1247 1248 /** 1249 * Checks for a valid function name. 1250 * 1251 * This method check whether an expression contains a valid name of an 1252 * XPath function. 1253 * 1254 * @access private 1255 * @author Michael P. Mehl <mpm@phpxml.org> 1256 * @param string $expression Name of the function to be checked. 1257 * @return boolean This method returns true if the given name is a valid 1258 * XPath function name, otherwise false. 1259 * @see evaluate() 1260 */ 1261 function is_function ( $expression ) 1262 { 1263 // Check whether it's in the list of supported functions. 1264 if ( in_array($expression, $this->functions) ) 1265 { 1266 // It's a function. 1267 return true; 1268 } 1269 else 1270 { 1271 // It's not a function. 1272 return false; 1273 } 1274 } 1275 1276 /** 1277 * Evaluates a step of an XPath expression. 1278 * 1279 * This method tries to evaluate a step from an XPath expression at a 1280 * specific context. 1281 * 1282 * @access private 1283 * @author Michael P. Mehl <mpm@phpxml.org> 1284 * @param string $context Full document path of the context from 1285 * which starting the step should be evaluated. 1286 * @param array $steps Array containing the remaining steps of the 1287 * current XPath expression. 1288 * @return array This method returns an array containing all nodes 1289 * that are the result of evaluating the given XPath step. 1290 * @see evaluate() 1291 */ 1292 function evaluate_step ( $context, $steps ) 1293 { 1294 // Create an empty array for saving the nodes found. 1295 $nodes = array(); 1296 1297 // Check whether the context is an array of contexts. 1298 if ( is_array($context) ) 1299 { 1300 // Run through the array. 1301 foreach ( $context as $path ) 1302 { 1303 // Call this method for this single path. 1304 $nodes = array_merge($nodes, 1305 $this->evaluate_step($path, $steps)); 1306 } 1307 } 1308 else 1309 { 1310 // Get this step. 1311 $step = array_shift($steps); 1312 1313 // Create an array to save the new contexts. 1314 $contexts = array(); 1315 1316 // Get the axis of the current step. 1317 $axis = $this->get_axis($step, $context); 1318 1319 // Check whether it's a function. 1320 if ( $axis["axis"] == "function" ) 1321 { 1322 // Check whether an array was return by the function. 1323 if ( is_array($axis["node-test"]) ) 1324 { 1325 // Add the results to the list of contexts. 1326 $contexts = array_merge($contexts, $axis["node-test"]); 1327 } 1328 else 1329 { 1330 // Add the result to the list of contexts. 1331 $contexts[] = $axis["node-test"]; 1332 } 1333 } 1334 else 1335 { 1336 // Create the name of the method. 1337 $method = "handle_axis_".str_replace("-", "_", $axis["axis"]); 1338 1339 // Check whether the axis handler is defined. 1340 if ( !method_exists(&$this, $method) ) 1341 { 1342 // Display an error message. 1343 $this->display_error("While parsing an XPath expression, ". 1344 "the axis \"%s\" could not be handled, because this ". 1345 "version does not support this axis.", $axis["axis"]); 1346 } 1347 1348 // Perform an axis action. 1349 $contexts = call_user_method($method, &$this, $axis, $context); 1350 1351 // Check whether there are predicates. 1352 if ( count($axis["predicate"]) > 0 ) 1353 { 1354 // Check whether each node fits the predicates. 1355 $contexts = $this->check_predicates($contexts, 1356 $axis["predicate"]); 1357 } 1358 } 1359 1360 // Check whether there are more steps left. 1361 if ( count($steps) > 0 ) 1362 { 1363 // Continue the evaluation of the next steps. 1364 $nodes = $this->evaluate_step($contexts, $steps); 1365 } 1366 else 1367 { 1368 // Save the found contexts. 1369 $nodes = $contexts; 1370 } 1371 } 1372 1373 // Return the nodes found. 1374 return $nodes; 1375 } 1376 1377 /** 1378 * Evaluates an XPath function 1379 * 1380 * This method evaluates a given XPath function with its arguments on a 1381 * specific node of the document. 1382 * 1383 * @access private 1384 * @author Michael P. Mehl <mpm@phpxml.org> 1385 * @param string $function Name of the function to be evaluated. 1386 * @param string $arguments String containing the arguments being 1387 * passed to the function. 1388 * @param string $node Full path to the document node on which the 1389 * function should be evaluated. 1390 * @return mixed This method returns the result of the evaluation of 1391 * the function. Depending on the function the type of the 1392 * return value can be different. 1393 * @see evaluate() 1394 */ 1395 function evaluate_function ( $function, $arguments, $node ) 1396 { 1397 // Remove whitespaces. 1398 $function = trim($function); 1399 $arguments = trim($arguments); 1400 1401 // Create the name of the function handling function. 1402 $method = "handle_function_".str_replace("-", "_", $function); 1403 1404 // Check whether the function handling function is available. 1405 if ( !method_exists(&$this, $method) ) 1406 { 1407 // Display an error message. 1408 $this->display_error("While parsing an XPath expression, ". 1409 "the function \"%s\" could not be handled, because this ". 1410 "version does not support this function.", $function); 1411 } 1412 1413 // Return the result of the function. 1414 return call_user_method($method, &$this, $node, $arguments); 1415 } 1416 1417 /** 1418 * Evaluates a predicate on a node. 1419 * 1420 * This method tries to evaluate a predicate on a given node. 1421 * 1422 * @access private 1423 * @author Michael P. Mehl <mpm@phpxml.org> 1424 * @param string $node Full path of the node on which the predicate 1425 * should be evaluated. 1426 * @param string $predicate String containing the predicate expression 1427 * to be evaluated. 1428 * @return mixed This method is called recursively. The first call should 1429 * return a boolean value, whether the node matches the predicate 1430 * or not. Any call to the method being made during the recursion 1431 * may also return other types for further processing. 1432 * @see evaluate() 1433 */ 1434 function evaluate_predicate ( $node, $predicate ) 1435 { 1436 // Set the default position and the type of the operator. 1437 $position = 0; 1438 $operator = ""; 1439 1440 // Run through all operators and try to find them. 1441 foreach ( $this->operators as $expression ) 1442 { 1443 // Check whether a position was already found. 1444 if ( $position <= 0 ) 1445 { 1446 // Try to find the operator. 1447 $position = $this->search_string($predicate, $expression); 1448 1449 // Check whether a operator was found. 1450 if ( $position > 0 ) 1451 { 1452 // Save the operator. 1453 $operator = $expression; 1454 1455 // Check whether it's the equal operator. 1456 if ( $operator == "=" ) 1457 { 1458 // Also look for other operators containing the 1459 // equal sign. 1460 if ( $this->search_string($predicate, "!=") == 1461 ( $position - 1 ) ) 1462 { 1463 // Get the new position. 1464 $position = $this->search_string($predicate, "!="); 1465 1466 // Save the new operator. 1467 $operator = "!="; 1468 } 1469 if ( $this->search_string($predicate, "<=") == 1470 ( $position - 1 ) ) 1471 { 1472 // Get the new position. 1473 $position = $this->search_string($predicate, "<="); 1474 1475 // Save the new operator. 1476 $operator = "<="; 1477 } 1478 if ( $this->search_string($predicate, ">=") == 1479 ( $position - 1 ) ) 1480 { 1481 // Get the new position. 1482 $position = $this->search_string($predicate, ">="); 1483 1484 // Save the new operator. 1485 $operator = ">="; 1486 } 1487 } 1488 } 1489 } 1490 } 1491 1492 // Check whether the operator is a - sign. 1493 if ( $operator == "-" ) 1494 { 1495 // Check whether it's not a function containing a - in its name. 1496 foreach ( $this->functions as $function ) 1497 { 1498 // Check whether there's a - sign in the function name. 1499 if ( ereg("-", $function) ) 1500 { 1501 // Get the position of the - in the function name. 1502 $sign = strpos($function, "-"); 1503 1504 // Extract a substring from the predicate. 1505 $sub = substr($predicate, $position - $sign, 1506 strlen($function)); 1507 1508 // Check whether it's the function. 1509 if ( $sub == $function ) 1510 { 1511 // Don't use the operator. 1512 $operator = ""; 1513 $position = -1; 1514 } 1515 } 1516 } 1517 } 1518 elseif ( $operator == "*" ) 1519 { 1520 // Get some substrings. 1521 $character = substr($predicate, $position - 1, 1); 1522 $attribute = substr($predicate, $position - 11, 11); 1523 1524 // Check whether it's an attribute selection. 1525 if ( ( $character == "@" ) || ( $attribute == "attribute::" ) ) 1526 { 1527 // Don't use the operator. 1528 $operator = ""; 1529 $position = -1; 1530 } 1531 } 1532 1533 // Check whether an operator was found. 1534 if ( $position > 0 ) 1535 { 1536 // Get the left and the right part of the expression. 1537 $left = substr($predicate, 0, $position); 1538 $right = substr($predicate, $position + strlen($operator)); 1539 1540 // Remove whitespaces. 1541 $left = trim($left); 1542 $right = trim($right); 1543 1544 // Evaluate the left and the right part. 1545 $left = $this->evaluate_predicate($node, $left); 1546 $right = $this->evaluate_predicate($node, $right); 1547 1548 // Check the kind of operator. 1549 switch ( $operator ) 1550 { 1551 case " or ": 1552 // Return the two results connected by an "or". 1553 return ( $left or $right ); 1554 1555 case " and ": 1556 // Return the two results connected by an "and". 1557 return ( $left and $right ); 1558 1559 case "=": 1560 // Compare the two results. 1561 return ( $left == $right ); 1562 1563 case "!=": 1564 // Check whether the two results are not equal. 1565 return ( $left != $right ); 1566 1567 case "<=": 1568 // Compare the two results. 1569 return ( $left <= $right ); 1570 1571 case "<": 1572 // Compare the two results. 1573 return ( $left < $right ); 1574 1575 case ">=": 1576 // Compare the two results. 1577 return ( $left >= $right ); 1578 1579 case ">": 1580 // Compare the two results. 1581 return ( $left > $right ); 1582 1583 case "+": 1584 // Return the result by adding one result to the other. 1585 return ( $left + $right ); 1586 1587 case "-": 1588 // Return the result by decrease one result by the other. 1589 return ( $left - $right ); 1590 1591 case "*": 1592 // Return a multiplication of the two results. 1593 return ( $left * $right ); 1594 1595 case " div ": 1596 // Return a division of the two results. 1597 if ( $right == 0 ) 1598 { 1599 // Display an error message. 1600 $this->display_error("While parsing an XPath ". 1601 "predicate, a error due a division by zero ". 1602 "occured."); 1603 } 1604 else 1605 { 1606 // Return the result of the division. 1607 return ( $left / $right ); 1608 } 1609 break; 1610 1611 case " mod ": 1612 // Return a modulo of the two results. 1613 return ( $left % $right ); 1614 } 1615 } 1616 1617 // Check whether the predicate is a function. 1618 if ( ereg("\(", $predicate) ) 1619 { 1620 // Get the position of the first bracket. 1621 $start = strpos($predicate, "("); 1622 $end = strpos($predicate, ")", $start); 1623 1624 // Get everything before, between and after the brackets. 1625 $before = substr($predicate, 0, $start); 1626 $between = substr($predicate, $start + 1, $end - $start - 1); 1627 $after = substr($predicate, $end + 1); 1628 1629 // Trim each string. 1630 $before = trim($before); 1631 $between = trim($between); 1632 $after = trim($after); 1633 1634 // Check whether there's something after the bracket. 1635 if ( !empty($after) ) 1636 { 1637 // Display an error message. 1638 $this->display_error("While parsing an XPath expression ". 1639 "there was found an error in the predicate \"%s\", ". 1640 "because after a closing bracket there was found ". 1641 "something unknown.", str_replace($predicate, 1642 "<b>".$predicate."</b>", $this->xpath)); 1643 } 1644 1645 // Check whether it's a function. 1646 if ( empty($before) && empty($after) ) 1647 { 1648 // Evaluate the content of the brackets. 1649 return $this->evaluate_predicate($node, $between); 1650 } 1651 elseif ( $this->is_function($before) ) 1652 { 1653 // Return the evaluated function. 1654 return $this->evaluate_function($before, $between, $node); 1655 } 1656 else 1657 { 1658 // Display an error message. 1659 $this->display_error("While parsing a predicate in an XPath ". 1660 "expression, a function \"%s\" was found, which is not ". 1661 "yet supported by the parser.", str_replace($before, 1662 "<b>".$before."</b>", $this->xpath)); 1663 } 1664 } 1665 1666 // Check whether the predicate is just a digit. 1667 if ( ereg("^[0-9]+(\.[0-9]+)?$", $predicate) || 1668 ereg("^\.[0-9]+$", $predicate) ) 1669 { 1670 // Return the value of the digit. 1671 return doubleval($predicate); 1672 } 1673 1674 // Check whether it's an XPath expression. 1675 $result = $this->evaluate($predicate, $node); 1676 if ( count($result) > 0 ) 1677 { 1678 // Convert the array. 1679 $result = explode("|", implode("|", $result)); 1680 1681 // Get the value of the first result. 1682 $value = $this->get_content($result[0]); 1683 1684 // Return the value. 1685 return $value; 1686 } 1687 1688 // Return the predicate as a string. 1689 return $predicate; 1690 } 1691 1692 /** 1693 * Checks whether a node matches predicates. 1694 * 1695 * This method checks whether a list of nodes passed to this method match 1696 * a given list of predicates. 1697 * 1698 * @access private 1699 * @author Michael P. Mehl <mpm@phpxml.org> 1700 * @param array $nodes Array of full paths of all nodes to be tested. 1701 * @param array $predicates Array of predicates to use. 1702 * @return array The array returned by this method contains a list of 1703 * all nodes matching the given predicates. 1704 * @see evaluate_step() 1705 */ 1706 function check_predicates ( $nodes, $predicates ) 1707 { 1708 // Create an empty set of nodes. 1709 $result = array(); 1710 1711 // Run through all nodes. 1712 foreach ( $nodes as $node ) 1713 { 1714 // Create a variable whether to add this node to the node-set. 1715 $add = true; 1716 1717 // Run through all predicates. 1718 foreach ( $predicates as $predicate ) 1719 { 1720 // Check whether the predicate is just an number. 1721 if ( ereg("^[0-9]+$", $predicate) ) 1722 { 1723 // Enhance the predicate. 1724 $predicate .= "=position()"; 1725 } 1726 1727 // Do the predicate check. 1728 $check = $this->evaluate_predicate($node, $predicate); 1729 1730 // Check whether it's a string. 1731 if ( is_string($check) && ( ( $check == "" ) || 1732 ( $check == $predicate ) ) ) 1733 { 1734 // Set the result to false. 1735 $check = false; 1736 } 1737 1738 // Check whether it's an integer. 1739 if ( is_int($check) ) 1740 { 1741 // Check whether it's the current position. 1742 if ( $check == $this->handle_function_position($node, "") ) 1743 { 1744 // Set it to true. 1745 $check = true; 1746 } 1747 else 1748 { 1749 // Set it to false. 1750 $check = false; 1751 } 1752 } 1753 1754 // Check whether the predicate is OK for this node. 1755 $add = $add && $check; 1756 } 1757 1758 // Check whether to add this node to the node-set. 1759 if ( $add ) 1760 { 1761 // Add the node to the node-set. 1762 $result[] = $node; 1763 } 1764 } 1765 1766 // Return the array of nodes. 1767 return $result; 1768 } 1769 1770 /** 1771 * Checks whether a node matches a node-test. 1772 * 1773 * This method checks whether a node in the document matches a given 1774 * node-test. 1775 * 1776 * @access private 1777 * @author Michael P. Mehl <mpm@phpxml.org> 1778 * @param string $context Full path of the node, which should be tested 1779 * for matching the node-test. 1780 * @param string $node_test String containing the node-test for the 1781 * node. 1782 * @return boolean This method returns true if the node matches the 1783 * node-test, otherwise false. 1784 * @see evaluate() 1785 */ 1786 function check_node_test ( $context, $node_test ) 1787 { 1788 // Check whether it's a function. 1789 if ( ereg("\(", $node_test) ) 1790 { 1791 // Get the type of function to use. 1792 $function = $this->prestr($node_test, "("); 1793 1794 // Check whether the node fits the method. 1795 switch ( $function ) 1796 { 1797 case "node": 1798 // Add this node to the list of nodes. 1799 return true; 1800 1801 case "text": 1802 // Check whether the node has some text. 1803 if ( !empty($this->nodes[$context]["text"]) ) 1804 { 1805 // Add this node to the list of nodes. 1806 return true; 1807 } 1808 break; 1809 1810 case "comment": 1811 // Check whether the node has some comment. 1812 if ( !empty($this->nodes[$context]["comment"]) ) 1813 { 1814 // Add this node to the list of nodes. 1815 return true; 1816 } 1817 break; 1818 1819 case "processing-instruction": 1820 // Get the literal argument. 1821 $literal = $this->afterstr($axis["node-test"], "("); 1822 1823 // Cut the literal. 1824 $literal = substr($literal, 0, strlen($literal) - 1); 1825 1826 // Check whether a literal was given. 1827 if ( !empty($literal) ) 1828 { 1829 // Check whether the node's processing instructions 1830 // are matching the literals given. 1831 if ( $this->nodes[$context] 1832 ["processing-instructions"] == $literal ) 1833 { 1834 // Add this node to the node-set. 1835 return true; 1836 } 1837 } 1838 else 1839 { 1840 // Check whether the node has processing 1841 // instructions. 1842 if ( !empty($this->nodes[$context] 1843 ["processing-instructions"]) ) 1844 { 1845 // Add this node to the node-set. 1846 return true; 1847 } 1848 } 1849 break; 1850 1851 default: 1852 // Display an error message. 1853 $this->display_error("While parsing an XPath ". 1854 "expression there was found an undefined ". 1855 "function called \"%s\".", 1856 str_replace($function, "<b>".$function."</b>", 1857 $this->xpath)); 1858 } 1859 } 1860 elseif ( $node_test == "*" ) 1861 { 1862 // Add this node to the node-set. 1863 return true; 1864 } 1865 elseif ( ereg("^[a-zA-Z0-9\-_]+", $node_test) ) 1866 { 1867 // Check whether the node-test can be fulfilled. 1868 if ( $this->nodes[$context]["name"] == $node_test ) 1869 { 1870 // Add this node to the node-set. 1871 return true; 1872 } 1873 } 1874 else 1875 { 1876 // Display an error message. 1877 $this->display_error("While parsing the XPath expression \"%s\" ". 1878 "an empty and therefore invalid node-test has been found.", 1879 $this->xpath); 1880 } 1881 1882 // Don't add this context. 1883 return false; 1884 } 1885 1886 /** 1887 * Handles the XPath child axis. 1888 * 1889 * This method handles the XPath child axis. 1890 * 1891 * @access private 1892 * @author Michael P. Mehl <mpm@phpxml.org> 1893 * @param array $axis Array containing information about the axis. 1894 * @param string $context Node from which starting the axis should 1895 * be processed. 1896 * @return array This method returns an array containing all nodes 1897 * that were found during the evaluation of the given axis. 1898 * @see evaluate() 1899 */ 1900 function handle_axis_child ( $axis, $context ) 1901 { 1902 // Create an empty node-set. 1903 $nodes = array(); 1904 1905 // Get a list of all children. 1906 $children = $this->nodes[$context]["children"]; 1907 1908 // Check whether there are children. 1909 if ( !empty($children) ) 1910 { 1911 // Run through all children. 1912 foreach ( $children as $child_name => $child_position ) 1913 { 1914 // Run through all childs with this name. 1915 for ( $i = 1; $i <= $child_position; $i++ ) 1916 { 1917 // Create the path of the child. 1918 $child = $context."/".$child_name."[".$i."]"; 1919 1920 // Check whether 1921 if ( $this->check_node_test($child, $axis["node-test"]) ) 1922 { 1923 // Add the child to the node-set. 1924 $nodes[] = $child; 1925 } 1926 } 1927 } 1928 } 1929 1930 // Return the nodeset. 1931 return $nodes; 1932 } 1933 1934 /** 1935 * Handles the XPath parent axis. 1936 * 1937 * This method handles the XPath parent axis. 1938 * 1939 * @access private 1940 * @author Michael P. Mehl <mpm@phpxml.org> 1941 * @param array $axis Array containing information about the axis. 1942 * @param string $context Node from which starting the axis should 1943 * be processed. 1944 * @return array This method returns an array containing all nodes 1945 * that were found during the evaluation of the given axis. 1946 * @see evaluate() 1947 */ 1948 function handle_axis_parent ( $axis, $context ) 1949 { 1950 // Create an empty node-set. 1951 $nodes = array(); 1952 1953 // Check whether the parent matches the node-test. 1954 if ( $this->check_node_test($this->nodes[$context]["parent"], 1955 $axis["node-test"]) ) 1956 { 1957 // Add this node to the list of nodes. 1958 $nodes[] = $this->nodes[$context]["parent"]; 1959 } 1960 1961 // Return the nodeset. 1962 return $nodes; 1963 } 1964 1965 /** 1966 * Handles the XPath attribute axis. 1967 * 1968 * This method handles the XPath attribute axis. 1969 * 1970 * @access private 1971 * @author Michael P. Mehl <mpm@phpxml.org> 1972 * @param array $axis Array containing information about the axis. 1973 * @param string $context Node from which starting the axis should 1974 * be processed. 1975 * @return array This method returns an array containing all nodes 1976 * that were found during the evaluation of the given axis. 1977 * @see evaluate() 1978 */ 1979 function handle_axis_attribute ( $axis, $context ) 1980 { 1981 // Create an empty node-set. 1982 $nodes = array(); 1983 1984 // Check whether all nodes should be selected. 1985 if ( $axis["node-test"] == "*" ) 1986 { 1987 // Check whether there are attributes. 1988 if ( count($this->nodes[$context]["attributes"]) > 0 ) 1989 { 1990 // Run through the attributes. 1991 foreach ( $this->nodes[$context]["attributes"] as 1992 $key => $value ) 1993 { 1994 // Add this node to the node-set. 1995 $nodes[] = $context."/attribute::".$key; 1996 } 1997 } 1998 } 1999 elseif ( !empty($this->nodes[$context]["attributes"] 2000 [$axis["node-test"]]) ) 2001 { 2002 // Add this node to the node-set. 2003 $nodes[] = $context."/attribute::".$axis["node-test"]; 2004 } 2005 2006 // Return the nodeset. 2007 return $nodes; 2008 } 2009 2010 /** 2011 * Handles the XPath self axis. 2012 * 2013 * This method handles the XPath self axis. 2014 * 2015 * @access private 2016 * @author Michael P. Mehl <mpm@phpxml.org> 2017 * @param array $axis Array containing information about the axis. 2018 * @param string $context Node from which starting the axis should 2019 * be processed. 2020 * @return array This method returns an array containing all nodes 2021 * that were found during the evaluation of the given axis. 2022 * @see evaluate() 2023 */ 2024 function handle_axis_self ( $axis, $context ) 2025 { 2026 // Create an empty node-set. 2027 $nodes = array(); 2028 2029 // Check whether the context match the node-test. 2030 if ( $this->check_node_test($context, $axis["node-test"]) ) 2031 { 2032 // Add this node to the node-set. 2033 $nodes[] = $context; 2034 } 2035 2036 // Return the nodeset. 2037 return $nodes; 2038 } 2039 2040 /** 2041 * Handles the XPath descendant axis. 2042 * 2043 * This method handles the XPath descendant axis. 2044 * 2045 * @access private 2046 * @author Michael P. Mehl <mpm@phpxml.org> 2047 * @param array $axis Array containing information about the axis. 2048 * @param string $context Node from which starting the axis should 2049 * be processed. 2050 * @return array This method returns an array containing all nodes 2051 * that were found during the evaluation of the given axis. 2052 * @see evaluate() 2053 */ 2054 function handle_axis_descendant ( $axis, $context ) 2055 { 2056 // Create an empty node-set. 2057 $nodes = array(); 2058 2059 // Check whether the current node has children. 2060 if ( count($this->nodes[$context]["children"]) > 0 ) 2061 { 2062 // Get a list of children. 2063 $children = $this->nodes[$context]["children"]; 2064 2065 // Run through all children. 2066 foreach ( $children as $child_name => $child_position ) 2067 { 2068 // Run through all children of this name. 2069 for ( $i = 1; $i <= $child_position; $i++ ) 2070 { 2071 // Create the full path for the children. 2072 $child = $context."/".$child_name."[".$i."]"; 2073 2074 // Check whether the child matches the node-test. 2075 if ( $this->check_node_test($child, $axis["node-test"]) ) 2076 { 2077 // Add the child to the list of nodes. 2078 $nodes[] = $child; 2079 } 2080 2081 // Recurse to the next level. 2082 $nodes = array_merge($nodes, 2083 $this->handle_axis_descendant($axis, $child)); 2084 } 2085 } 2086 } 2087 2088 // Return the nodeset. 2089 return $nodes; 2090 } 2091 2092 /** 2093 * Handles the XPath ancestor axis. 2094 * 2095 * This method handles the XPath ancestor axis. 2096 * 2097 * @access private 2098 * @author Michael P. Mehl <mpm@phpxml.org> 2099 * @param array $axis Array containing information about the axis. 2100 * @param string $context Node from which starting the axis should 2101 * be processed. 2102 * @return array This method returns an array containing all nodes 2103 * that were found during the evaluation of the given axis. 2104 * @see evaluate() 2105 */ 2106 function handle_axis_ancestor ( $axis, $context ) 2107 { 2108 // Create an empty node-set. 2109 $nodes = array(); 2110 2111 // Get the parent of the current node. 2112 $parent = $this->nodes[$context]["parent"]; 2113 2114 // Check whether the parent isn't empty. 2115 if ( !empty($parent) ) 2116 { 2117 // Check whether the parent matches the node-test. 2118 if ( $this->check_node_test($parent, $axis["node-test"]) ) 2119 { 2120 // Add the parent to the list of nodes. 2121 $nodes[] = $parent; 2122 } 2123 2124 // Handle all other ancestors. 2125 $nodes = array_merge($nodes, 2126 $this->handle_axis_ancestor($axis, $parent)); 2127 } 2128 2129 // Return the nodeset. 2130 return $nodes; 2131 } 2132 2133 /** 2134 * Handles the XPath namespace axis. 2135 * 2136 * This method handles the XPath namespace axis. 2137 * 2138 * @access private 2139 * @author Michael P. Mehl <mpm@phpxml.org> 2140 * @param array $axis Array containing information about the axis. 2141 * @param string $context Node from which starting the axis should 2142 * be processed. 2143 * @return array This method returns an array containing all nodes 2144 * that were found during the evaluation of the given axis. 2145 * @see evaluate() 2146 */ 2147 function handle_axis_namespace ( $axis, $context ) 2148 { 2149 // Create an empty node-set. 2150 $nodes = array(); 2151 2152 // Check whether all nodes should be selected. 2153 if ( !empty($this->nodes[$context]["namespace"]) ) 2154 { 2155 // Add this node to the node-set. 2156 $nodes[] = $context; 2157 } 2158 2159 // Return the nodeset. 2160 return $nodes; 2161 } 2162 2163 /** 2164 * Handles the XPath following axis. 2165 * 2166 * This method handles the XPath following axis. 2167 * 2168 * @access private 2169 * @author Michael P. Mehl <mpm@phpxml.org> 2170 * @param array $axis Array containing information about the axis. 2171 * @param string $context Node from which starting the axis should 2172 * be processed. 2173 * @return array This method returns an array containing all nodes 2174 * that were found during the evaluation of the given axis. 2175 * @see evaluate() 2176 */ 2177 function handle_axis_following ( $axis, $context ) 2178 { 2179 // Create an empty node-set. 2180 $nodes = array(); 2181 2182 // Get the current document position. 2183 $position = $this->nodes[$context]["document-position"]; 2184 2185 // Create a flag, whether we already found the context node. 2186 $found = false; 2187 2188 // Run through all nodes of the document. 2189 foreach ( $this->nodes as $node => $data ) 2190 { 2191 // Check whether the context node has already been found. 2192 if ( $found ) 2193 { 2194 // Check whether the position is correct. 2195 if ( $this->nodes[$node]["document-position"] == $position ) 2196 { 2197 // Check whether the node fits the node-test. 2198 if ( $this->check_node_test($node, $axis["node-test"]) ) 2199 { 2200 // Add the node to the list of nodes. 2201 $nodes[] = $node; 2202 } 2203 } 2204 } 2205 2206 // Check whether this is the context node. 2207 if ( $node == $context ) 2208 { 2209 // After this we'll look for more nodes. 2210 $found = true; 2211 } 2212 } 2213 2214 // Return the nodeset. 2215 return $nodes; 2216 } 2217 2218 /** 2219 * Handles the XPath preceding axis. 2220 * 2221 * This method handles the XPath preceding axis. 2222 * 2223 * @access private 2224 * @author Michael P. Mehl <mpm@phpxml.org> 2225 * @param array $axis Array containing information about the axis. 2226 * @param string $context Node from which starting the axis should 2227 * be processed. 2228 * @return array This method returns an array containing all nodes 2229 * that were found during the evaluation of the given axis. 2230 * @see evaluate() 2231 */ 2232 function handle_axis_preceding ( $axis, $context ) 2233 { 2234 // Create an empty node-set. 2235 $nodes = array(); 2236 2237 // Get the current document position. 2238 $position = $this->nodes[$context]["document-position"]; 2239 2240 // Create a flag, whether we already found the context node. 2241 $found = true; 2242 2243 // Run through all nodes of the document. 2244 foreach ( $this->nodes as $node => $data ) 2245 { 2246 // Check whether this is the context node. 2247 if ( $node == $context ) 2248 { 2249 // After this we won't look for more nodes. 2250 $found = false; 2251 } 2252 2253 // Check whether the context node has already been found. 2254 if ( $found ) 2255 { 2256 // Check whether the position is correct. 2257 if ( $this->nodes[$node]["document-position"] == $position ) 2258 { 2259 // Check whether the node fits the node-test. 2260 if ( $this->check_node_test($node, $axis["node-test"]) ) 2261 { 2262 // Add the node to the list of nodes. 2263 $nodes[] = $node; 2264 } 2265 } 2266 } 2267 } 2268 2269 // Return the nodeset. 2270 return $nodes; 2271 } 2272 2273 /** 2274 * Handles the XPath following-sibling axis. 2275 * 2276 * This method handles the XPath following-sibling axis. 2277 * 2278 * @access private 2279 * @author Michael P. Mehl <mpm@phpxml.org> 2280 * @param array $axis Array containing information about the axis. 2281 * @param string $context Node from which starting the axis should 2282 * be processed. 2283 * @return array This method returns an array containing all nodes 2284 * that were found during the evaluation of the given axis. 2285 * @see evaluate() 2286 */ 2287 function handle_axis_following_sibling ( $axis, $context ) 2288 { 2289 // Create an empty node-set. 2290 $nodes = array(); 2291 2292 // Get all children from the parent. 2293 $siblings = $this->handle_axis_child($axis, 2294 $this->nodes[$context]["parent"]); 2295 2296 // Create a flag whether the context node was already found. 2297 $found = false; 2298 2299 // Run through all siblings. 2300 foreach ( $siblings as $sibling ) 2301 { 2302 // Check whether the context node was already found. 2303 if ( $found ) 2304 { 2305 // Check whether the sibling is a real sibling. 2306 if ( $this->nodes[$sibling]["name"] == 2307 $this->nodes[$context]["name"] ) 2308 { 2309 // Check whether the sibling matches the node-test. 2310 if ( $this->check_node_test($sibling, $axis["node-test"]) ) 2311 { 2312 // Add the sibling to the list of nodes. 2313 $nodes[] = $sibling; 2314 } 2315 } 2316 } 2317 2318 // Check whether this is the context node. 2319 if ( $sibling == $context ) 2320 { 2321 // Continue looking for other siblings. 2322 $found = true; 2323 } 2324 } 2325 2326 // Return the nodeset. 2327 return $nodes; 2328 } 2329 2330 /** 2331 * Handles the XPath preceding-sibling axis. 2332 * 2333 * This method handles the XPath preceding-sibling axis. 2334 * 2335 * @access private 2336 * @author Michael P. Mehl <mpm@phpxml.org> 2337 * @param array $axis Array containing information about the axis. 2338 * @param string $context Node from which starting the axis should 2339 * be processed. 2340 * @return array This method returns an array containing all nodes 2341 * that were found during the evaluation of the given axis. 2342 * @see evaluate() 2343 */ 2344 function handle_axis_preceding_sibling ( $axis, $context ) 2345 { 2346 // Create an empty node-set. 2347 $nodes = array(); 2348 2349 // Get all children from the parent. 2350 $siblings = $this->handle_axis_child($axis, 2351 $this->nodes[$context]["parent"]); 2352 2353 // Create a flag whether the context node was already found. 2354 $found = true; 2355 2356 // Run through all siblings. 2357 foreach ( $siblings as $sibling ) 2358 { 2359 // Check whether this is the context node. 2360 if ( $sibling == $context ) 2361 { 2362 // Don't continue looking for other siblings. 2363 $found = false; 2364 } 2365 2366 // Check whether the context node was already found. 2367 if ( $found ) 2368 { 2369 // Check whether the sibling is a real sibling. 2370 if ( $this->nodes[$sibling]["name"] == 2371 $this->nodes[$context]["name"] ) 2372 { 2373 // Check whether the sibling matches the node-test. 2374 if ( $this->check_node_test($sibling, $axis["node-test"]) ) 2375 { 2376 // Add the sibling to the list of nodes. 2377 $nodes[] = $sibling; 2378 } 2379 } 2380 } 2381 } 2382 2383 // Return the nodeset. 2384 return $nodes; 2385 } 2386 2387 /** 2388 * Handles the XPath descendant-or-self axis. 2389 * 2390 * This method handles the XPath descendant-or-self axis. 2391 * 2392 * @access private 2393 * @author Michael P. Mehl <mpm@phpxml.org> 2394 * @param array $axis Array containing information about the axis. 2395 * @param string $context Node from which starting the axis should 2396 * be processed. 2397 * @return array This method returns an array containing all nodes 2398 * that were found during the evaluation of the given axis. 2399 * @see evaluate() 2400 */ 2401 function handle_axis_descendant_or_self ( $axis, $context ) 2402 { 2403 // Create an empty node-set. 2404 $nodes = array(); 2405 2406 // Read the nodes. 2407 $nodes = array_merge( 2408 $this->handle_axis_descendant($axis, $context), 2409 $this->handle_axis_self($axis, $context)); 2410 2411 // Return the nodeset. 2412 return $nodes; 2413 } 2414 2415 /** 2416 * Handles the XPath ancestor-or-self axis. 2417 * 2418 * This method handles the XPath ancestor-or-self axis. 2419 * 2420 * @access private 2421 * @author Michael P. Mehl <mpm@phpxml.org> 2422 * @param array $axis Array containing information about the axis. 2423 * @param string $context Node from which starting the axis should 2424 * be processed. 2425 * @return array This method returns an array containing all nodes 2426 * that were found during the evaluation of the given axis. 2427 * @see evaluate() 2428 */ 2429 function handle_axis_ancestor_or_self ( $axis, $context ) 2430 { 2431 // Create an empty node-set. 2432 $nodes = array(); 2433 2434 // Read the nodes. 2435 $nodes = array_merge( 2436 $this->handle_axis_ancestor($axis, $context), 2437 $this->handle_axis_self($axis, $context)); 2438 2439 // Return the nodeset. 2440 return $nodes; 2441 } 2442 2443 /** 2444 * Handles the XPath function last. 2445 * 2446 * This method handles the XPath function last. 2447 * 2448 * @access private 2449 * @author Michael P. Mehl <mpm@phpxml.org> 2450 * @param string $node Full path of the node on which the function 2451 * should be processed. 2452 * @param string $arguments String containing the arguments that were 2453 * passed to the function. 2454 * @return mixed Depending on the type of function being processed this 2455 * method returns different types. 2456 * @see evaluate() 2457 */ 2458 function handle_function_last ( $node, $arguments ) 2459 { 2460 // Calculate the size of the context. 2461 $parent = $this->nodes[$node]["parent"]; 2462 $children = $this->nodes[$parent]["children"]; 2463 $context = $children[$this->nodes[$node]["name"]]; 2464 2465 // Return the size. 2466 return $context; 2467 } 2468 2469 /** 2470 * Handles the XPath function position. 2471 * 2472 * This method handles the XPath function position. 2473 * 2474 * @access private 2475 * @author Michael P. Mehl <mpm@phpxml.org> 2476 * @param string $node Full path of the node on which the function 2477 * should be processed. 2478 * @param string $arguments String containing the arguments that were 2479 * passed to the function. 2480 * @return mixed Depending on the type of function being processed this 2481 * method returns different types. 2482 * @see evaluate() 2483 */ 2484 function handle_function_position ( $node, $arguments ) 2485 { 2486 // return the context-position. 2487 return $this->nodes[$node]["context-position"]; 2488 } 2489 2490 /** 2491 * Handles the XPath function count. 2492 * 2493 * This method handles the XPath function count. 2494 * 2495 * @access private 2496 * @author Michael P. Mehl <mpm@phpxml.org> 2497 * @param string $node Full path of the node on which the function 2498 * should be processed. 2499 * @param string $arguments String containing the arguments that were 2500 * passed to the function. 2501 * @return mixed Depending on the type of function being processed this 2502 * method returns different types. 2503 * @see evaluate() 2504 */ 2505 function handle_function_count ( $node, $arguments ) 2506 { 2507 // Evaluate the argument of the method as an XPath and return 2508 // the number of results. 2509 return count($this->evaluate($arguments, $node)); 2510 } 2511 2512 /** 2513 * Handles the XPath function id. 2514 * 2515 * This method handles the XPath function id. 2516 * 2517 * @access private 2518 * @author Michael P. Mehl <mpm@phpxml.org> 2519 * @param string $node Full path of the node on which the function 2520 * should be processed. 2521 * @param string $arguments String containing the arguments that were 2522 * passed to the function. 2523 * @return mixed Depending on the type of function being processed this 2524 * method returns different types. 2525 * @see evaluate() 2526 */ 2527 function handle_function_id ( $node, $arguments ) 2528 { 2529 // Trim the arguments. 2530 $arguments = trim($arguments); 2531 2532 // Now split the arguments. 2533 $arguments = explode(" ", $arguments); 2534 2535 // Check whether 2536 2537 // Create a list of nodes. 2538 $nodes = array(); 2539 2540 // Run through all document node. 2541 foreach ( $this->nodes as $node => $position ) 2542 { 2543 // Check whether the node has the ID we're looking for. 2544 if ( in_array($this->nodes[$node]["attributes"]["id"], 2545 $arguments) ) 2546 { 2547 // Add this node to the list of nodes. 2548 $nodes[] = $node; 2549 } 2550 } 2551 2552 // Return the list of nodes. 2553 return $nodes; 2554 } 2555 2556 /** 2557 * Handles the XPath function name. 2558 * 2559 * This method handles the XPath function name. 2560 * 2561 * @access private 2562 * @author Michael P. Mehl <mpm@phpxml.org> 2563 * @param string $node Full path of the node on which the function 2564 * should be processed. 2565 * @param string $arguments String containing the arguments that were 2566 * passed to the function. 2567 * @return mixed Depending on the type of function being processed this 2568 * method returns different types. 2569 * @see evaluate() 2570 */ 2571 function handle_function_name ( $node, $arguments ) 2572 { 2573 // Return the name of the node. 2574 return $this->nodes[$node]["name"]; 2575 } 2576 2577 /** 2578 * Handles the XPath function string. 2579 * 2580 * This method handles the XPath function string. 2581 * 2582 * @access private 2583 * @author Michael P. Mehl <mpm@phpxml.org> 2584 * @param string $node Full path of the node on which the function 2585 * should be processed. 2586 * @param string $arguments String containing the arguments that were 2587 * passed to the function. 2588 * @return mixed Depending on the type of function being processed this 2589 * method returns different types. 2590 * @see evaluate() 2591 */ 2592 function handle_function_string ( $node, $arguments ) 2593 { 2594 // Check what type of parameter is given 2595 if ( ereg("^[0-9]+(\.[0-9]+)?$", $arguments) || 2596 ereg("^\.[0-9]+$", $arguments) ) 2597 { 2598 // Convert the digits to a number. 2599 $number = doubleval($arguments); 2600 2601 // Return the number. 2602 return strval($number); 2603 } 2604 elseif ( is_bool($arguments) ) 2605 { 2606 // Check whether it's true. 2607 if ( $arguments == true ) 2608 { 2609 // Return true as a string. 2610 return "true"; 2611 } 2612 else 2613 { 2614 // Return false as a string. 2615 return "false"; 2616 } 2617 } 2618 elseif ( !empty($arguments) ) 2619 { 2620 // Use the argument as an XPath. 2621 $result = $this->evaluate($arguments, $node); 2622 2623 // Get the first argument. 2624 $result = explode("|", implode("|", $result)); 2625 2626 // Return the first result as a string. 2627 return $result[0]; 2628 } 2629 elseif ( empty($arguments) ) 2630 { 2631 // Return the current node. 2632 return $node; 2633 } 2634 else 2635 { 2636 // Return an empty string. 2637 return ""; 2638 } 2639 } 2640 2641 /** 2642 * Handles the XPath function concat. 2643 * 2644 * This method handles the XPath function concat. 2645 * 2646 * @access private 2647 * @author Michael P. Mehl <mpm@phpxml.org> 2648 * @param string $node Full path of the node on which the function 2649 * should be processed. 2650 * @param string $arguments String containing the arguments that were 2651 * passed to the function. 2652 * @return mixed Depending on the type of function being processed this 2653 * method returns different types. 2654 * @see evaluate() 2655 */ 2656 function handle_function_concat ( $node, $arguments ) 2657 { 2658 // Split the arguments. 2659 $arguments = explode(",", $arguments); 2660 2661 // Run through each argument and evaluate it. 2662 for ( $i = 0; $i < sizeof($arguments); $i++ ) 2663 { 2664 // Trim each argument. 2665 $arguments[$i] = trim($arguments[$i]); 2666 2667 // Evaluate it. 2668 $arguments[$i] = $this->evaluate_predicate($node, $arguments[$i]); 2669 } 2670 2671 // Put the string together. 2672 $arguments = implode("", $arguments); 2673 2674 // Return the string. 2675 return $arguments; 2676 } 2677 2678 /** 2679 * Handles the XPath function starts-with. 2680 * 2681 * This method handles the XPath function starts-with. 2682 * 2683 * @access private 2684 * @author Michael P. Mehl <mpm@phpxml.org> 2685 * @param string $node Full path of the node on which the function 2686 * should be processed. 2687 * @param string $arguments String containing the arguments that were 2688 * passed to the function. 2689 * @return mixed Depending on the type of function being processed this 2690 * method returns different types. 2691 * @see evaluate() 2692 */ 2693 function handle_function_starts_with ( $node, $arguments ) 2694 { 2695 // Get the arguments. 2696 $first = trim($this->prestr($arguments, ",")); 2697 $second = trim($this->afterstr($arguments, ",")); 2698 2699 // Evaluate each argument. 2700 $first = $this->evaluate_predicate($node, $first); 2701 $second = $this->evaluate_predicate($node, $second); 2702 2703 // Check whether the first string starts with the second one. 2704 if ( ereg("^".$second, $first) ) 2705 { 2706 // Return true. 2707 return true; 2708 } 2709 else 2710 { 2711 // Return false. 2712 return false; 2713 } 2714 } 2715 2716 /** 2717 * Handles the XPath function contains. 2718 * 2719 * This method handles the XPath function contains. 2720 * 2721 * @access private 2722 * @author Michael P. Mehl <mpm@phpxml.org> 2723 * @param string $node Full path of the node on which the function 2724 * should be processed. 2725 * @param string $arguments String containing the arguments that were 2726 * passed to the function. 2727 * @return mixed Depending on the type of function being processed this 2728 * method returns different types. 2729 * @see evaluate() 2730 */ 2731 function handle_function_contains ( $node, $arguments ) 2732 { 2733 // Get the arguments. 2734 $first = trim($this->prestr($arguments, ",")); 2735 $second = trim($this->afterstr($arguments, ",")); 2736 2737 // Evaluate each argument. 2738 $first = $this->evaluate_predicate($node, $first); 2739 $second = $this->evaluate_predicate($node, $second); 2740 2741 // Check whether the first string starts with the second one. 2742 if ( ereg($second, $first) ) 2743 { 2744 // Return true. 2745 return true; 2746 } 2747 else 2748 { 2749 // Return false. 2750 return false; 2751 } 2752 } 2753 2754 /** 2755 * Handles the XPath function substring-before. 2756 * 2757 * This method handles the XPath function substring-before. 2758 * 2759 * @access private 2760 * @author Michael P. Mehl <mpm@phpxml.org> 2761 * @param string $node Full path of the node on which the function 2762 * should be processed. 2763 * @param string $arguments String containing the arguments that were 2764 * passed to the function. 2765 * @return mixed Depending on the type of function being processed this 2766 * method returns different types. 2767 * @see evaluate() 2768 */ 2769 function handle_function_substring_before ( $node, $arguments ) 2770 { 2771 // Get the arguments. 2772 $first = trim($this->prestr($arguments, ",")); 2773 $second = trim($this->afterstr($arguments, ",")); 2774 2775 // Evaluate each argument. 2776 $first = $this->evaluate_predicate($node, $first); 2777 $second = $this->evaluate_predicate($node, $second); 2778 2779 // Return the substring. 2780 return $this->prestr(strval($first), strval($second)); 2781 } 2782 2783 /** 2784 * Handles the XPath function substring-after. 2785 * 2786 * This method handles the XPath function substring-after. 2787 * 2788 * @access private 2789 * @author Michael P. Mehl <mpm@phpxml.org> 2790 * @param string $node Full path of the node on which the function 2791 * should be processed. 2792 * @param string $arguments String containing the arguments that were 2793 * passed to the function. 2794 * @return mixed Depending on the type of function being processed this 2795 * method returns different types. 2796 * @see evaluate() 2797 */ 2798 function handle_function_substring_after ( $node, $arguments ) 2799 { 2800 // Get the arguments. 2801 $first = trim($this->prestr($arguments, ",")); 2802 $second = trim($this->afterstr($arguments, ",")); 2803 2804 // Evaluate each argument. 2805 $first = $this->evaluate_predicate($node, $first); 2806 $second = $this->evaluate_predicate($node, $second); 2807 2808 // Return the substring. 2809 return $this->afterstr(strval($first), strval($second)); 2810 } 2811 2812 /** 2813 * Handles the XPath function substring. 2814 * 2815 * This method handles the XPath function substring. 2816 * 2817 * @access private 2818 * @author Michael P. Mehl <mpm@phpxml.org> 2819 * @param string $node Full path of the node on which the function 2820 * should be processed. 2821 * @param string $arguments String containing the arguments that were 2822 * passed to the function. 2823 * @return mixed Depending on the type of function being processed this 2824 * method returns different types. 2825 * @see evaluate() 2826 */ 2827 function handle_function_substring ( $node, $arguments ) 2828 { 2829 // Split the arguments. 2830 $arguments = explode(",", $arguments); 2831 2832 // Run through all arguments. 2833 for ( $i = 0; $i < sizeof($arguments); $i++ ) 2834 { 2835 // Trim the string. 2836 $arguments[$i] = trim($arguments[$i]); 2837 2838 // Evaluate each argument. 2839 $arguments[$i] = $this->evaluate_predicate($node, $arguments[$i]); 2840 } 2841 2842 // Check whether a third argument was given. 2843 if ( !empty($arguments[2]) ) 2844 { 2845 // Return the substring. 2846 return substr(strval($arguments[0]), $arguments[1] - 1, 2847 $arguments[2]); 2848 } 2849 else 2850 { 2851 // Return the substring. 2852 return substr(strval($arguments[0]), $arguments[1] - 1); 2853 } 2854 } 2855 2856 /** 2857 * Handles the XPath function string-length. 2858 * 2859 * This method handles the XPath function string-length. 2860 * 2861 * @access private 2862 * @author Michael P. Mehl <mpm@phpxml.org> 2863 * @param string $node Full path of the node on which the function 2864 * should be processed. 2865 * @param string $arguments String containing the arguments that were 2866 * passed to the function. 2867 * @return mixed Depending on the type of function being processed this 2868 * method returns different types. 2869 * @see evaluate() 2870 */ 2871 function handle_function_string_length ( $node, $arguments ) 2872 { 2873 // Trim the argument. 2874 $arguments = trim($arguments); 2875 2876 // Evaluate the argument. 2877 $arguments = $this->evaluate_predicate($node, $arguments); 2878 2879 // Return the length of the string. 2880 return strlen(strval($arguments)); 2881 } 2882 2883 /** 2884 * Handles the XPath function translate. 2885 * 2886 * This method handles the XPath function translate. 2887 * 2888 * @access private 2889 * @author Michael P. Mehl <mpm@phpxml.org> 2890 * @param string $node Full path of the node on which the function 2891 * should be processed. 2892 * @param string $arguments String containing the arguments that were 2893 * passed to the function. 2894 * @return mixed Depending on the type of function being processed this 2895 * method returns different types. 2896 * @see evaluate() 2897 */ 2898 function handle_function_translate ( $node, $arguments ) 2899 { 2900 // Split the arguments. 2901 $arguments = explode(",", $arguments); 2902 2903 // Run through all arguments. 2904 for ( $i = 0; $i < sizeof($arguments); $i++ ) 2905 { 2906 // Trim the argument. 2907 $arguments[$i] = trim($arguments[$i]); 2908 2909 // Evaluate the argument. 2910 $arguments[$i] = $this->evaluate_predicate($node, $arguments[$i]); 2911 } 2912 2913 // Return the translated string. 2914 return strtr($arguments[0], $arguments[1], $arguments[2]); 2915 } 2916 2917 /** 2918 * Handles the XPath function boolean. 2919 * 2920 * This method handles the XPath function boolean. 2921 * 2922 * @access private 2923 * @author Michael P. Mehl <mpm@phpxml.org> 2924 * @param string $node Full path of the node on which the function 2925 * should be processed. 2926 * @param string $arguments String containing the arguments that were 2927 * passed to the function. 2928 * @return mixed Depending on the type of function being processed this 2929 * method returns different types. 2930 * @see evaluate() 2931 */ 2932 function handle_function_boolean ( $node, $arguments ) 2933 { 2934 // Trim the arguments. 2935 $arguments = trim($arguments); 2936 2937 // Check what type of parameter is given 2938 if ( ereg("^[0-9]+(\.[0-9]+)?$", $arguments) || 2939 ereg("^\.[0-9]+$", $arguments) ) 2940 { 2941 // Convert the digits to a number. 2942 $number = doubleval($arguments); 2943 2944 // Check whether the number zero. 2945 if ( $number == 0 ) 2946 { 2947 // Return false. 2948 return false; 2949 } 2950 else 2951 { 2952 // Return true. 2953 return true; 2954 } 2955 } 2956 elseif ( empty($arguments) ) 2957 { 2958 // Sorry, there were no arguments. 2959 return false; 2960 } 2961 else 2962 { 2963 // Try to evaluate the argument as an XPath. 2964 $result = $this->evaluate($arguments, $node); 2965 2966 // Check whether we found something. 2967 if ( count($result) > 0 ) 2968 { 2969 // Return true. 2970 return true; 2971 } 2972 else 2973 { 2974 // Return false. 2975 return false; 2976 } 2977 } 2978 } 2979 2980 /** 2981 * Handles the XPath function not. 2982 * 2983 * This method handles the XPath function not. 2984 * 2985 * @access private 2986 * @author Michael P. Mehl <mpm@phpxml.org> 2987 * @param string $node Full path of the node on which the function 2988 * should be processed. 2989 * @param string $arguments String containing the arguments that were 2990 * passed to the function. 2991 * @return mixed Depending on the type of function being processed this 2992 * method returns different types. 2993 * @see evaluate() 2994 */ 2995 function handle_function_not ( $node, $arguments ) 2996 { 2997 // Trim the arguments. 2998 $arguments = trim($arguments); 2999 3000 // Return the negative value of the content of the brackets. 3001 return !$this->evaluate_predicate($node, $arguments); 3002 } 3003 3004 /** 3005 * Handles the XPath function true. 3006 * 3007 * This method handles the XPath function true. 3008 * 3009 * @access private 3010 * @author Michael P. Mehl <mpm@phpxml.org> 3011 * @param string $node Full path of the node on which the function 3012 * should be processed. 3013 * @param string $arguments String containing the arguments that were 3014 * passed to the function. 3015 * @return mixed Depending on the type of function being processed this 3016 * method returns different types. 3017 * @see evaluate() 3018 */ 3019 function handle_function_true ( $node, $arguments ) 3020 { 3021 // Return true. 3022 return true; 3023 } 3024 3025 /** 3026 * Handles the XPath function false. 3027 * 3028 * This method handles the XPath function false. 3029 * 3030 * @access private 3031 * @author Michael P. Mehl <mpm@phpxml.org> 3032 * @param string $node Full path of the node on which the function 3033 * should be processed. 3034 * @param string $arguments String containing the arguments that were 3035 * passed to the function. 3036 * @return mixed Depending on the type of function being processed this 3037 * method returns different types. 3038 * @see evaluate() 3039 */ 3040 function handle_function_false ( $node, $arguments ) 3041 { 3042 // Return false. 3043 return false; 3044 } 3045 3046 /** 3047 * Handles the XPath function lang. 3048 * 3049 * This method handles the XPath function lang. 3050 * 3051 * @access private 3052 * @author Michael P. Mehl <mpm@phpxml.org> 3053 * @param string $node Full path of the node on which the function 3054 * should be processed. 3055 * @param string $arguments String containing the arguments that were 3056 * passed to the function. 3057 * @return mixed Depending on the type of function being processed this 3058 * method returns different types. 3059 * @see evaluate() 3060 */ 3061 function handle_function_lang ( $node, $arguments ) 3062 { 3063 // Trim the arguments. 3064 $arguments = trim($arguments); 3065 3066 // Check whether the node has an language attribute. 3067 if ( empty($this->nodes[$node]["attributes"]["xml:lang"]) ) 3068 { 3069 // Run through the ancestors. 3070 while ( !empty($node) ) 3071 { 3072 // Select the parent node. 3073 $node = $this->nodes[$node]["parent"]; 3074 3075 // Check whether there's a language definition. 3076 if ( !empty($this->nodes[$node]["attributes"]["xml:lang"]) ) 3077 { 3078 // Check whether it's the language, the user asks for. 3079 if ( eregi("^".$arguments, $this->nodes[$node] 3080 ["attributes"]["xml:lang"]) ) 3081 { 3082 // Return true. 3083 return true; 3084 } 3085 else 3086 { 3087 // Return false. 3088 return false; 3089 } 3090 } 3091 } 3092 3093 // Return false. 3094 return false; 3095 } 3096 else 3097 { 3098 // Check whether it's the language, the user asks for. 3099 if ( eregi("^".$arguments, $this->nodes[$node]["attributes"] 3100 ["xml:lang"]) ) 3101 { 3102 // Return true. 3103 return true; 3104 } 3105 else 3106 { 3107 // Return false. 3108 return false; 3109 } 3110 } 3111 } 3112 3113 /** 3114 * Handles the XPath function number. 3115 * 3116 * This method handles the XPath function number. 3117 * 3118 * @access private 3119 * @author Michael P. Mehl <mpm@phpxml.org> 3120 * @param string $node Full path of the node on which the function 3121 * should be processed. 3122 * @param string $arguments String containing the arguments that were 3123 * passed to the function. 3124 * @return mixed Depending on the type of function being processed this 3125 * method returns different types. 3126 * @see evaluate() 3127 */ 3128 function handle_function_number ( $node, $arguments ) 3129 { 3130 // Check the type of argument. 3131 if ( ereg("^[0-9]+(\.[0-9]+)?$", $arguments) || 3132 ereg("^\.[0-9]+$", $arguments) ) 3133 { 3134 // Return the argument as a number. 3135 return doubleval($arguments); 3136 } 3137 elseif ( is_bool($arguments) ) 3138 { 3139 // Check whether it's true. 3140 if ( $arguments == true ) 3141 { 3142 // Return 1. 3143 return 1; 3144 } 3145 else 3146 { 3147 // Return 0. 3148 return 0; 3149 } 3150 } 3151 } 3152 3153 /** 3154 * Handles the XPath function sum. 3155 * 3156 * This method handles the XPath function sum. 3157 * 3158 * @access private 3159 * @author Michael P. Mehl <mpm@phpxml.org> 3160 * @param string $node Full path of the node on which the function 3161 * should be processed. 3162 * @param string $arguments String containing the arguments that were 3163 * passed to the function. 3164 * @return mixed Depending on the type of function being processed this 3165 * method returns different types. 3166 * @see evaluate() 3167 */ 3168 function handle_function_sum ( $node, $arguments ) 3169 { 3170 // Trim the arguments. 3171 $arguments = trim($arguments); 3172 3173 // Evaluate the arguments as an XPath expression. 3174 $results = $this->evaluate($arguments, $node); 3175 3176 // Create a variable to save the sum. 3177 $sum = 0; 3178 3179 // Run through all results. 3180 foreach ( $results as $result ) 3181 { 3182 // Get the value of the node. 3183 $result = $this->get_content($result); 3184 3185 // Add it to the sum. 3186 $sum += doubleval($result); 3187 } 3188 3189 // Return the sum. 3190 return $sum; 3191 } 3192 3193 /** 3194 * Handles the XPath function floor. 3195 * 3196 * This method handles the XPath function floor. 3197 * 3198 * @access private 3199 * @author Michael P. Mehl <mpm@phpxml.org> 3200 * @param string $node Full path of the node on which the function 3201 * should be processed. 3202 * @param string $arguments String containing the arguments that were 3203 * passed to the function. 3204 * @return mixed Depending on the type of function being processed this 3205 * method returns different types. 3206 * @see evaluate() 3207 */ 3208 function handle_function_floor ( $node, $arguments ) 3209 { 3210 // Trim the arguments. 3211 $arguments = trim($arguments); 3212 3213 // Convert the arguments to a number. 3214 $arguments = doubleval($arguments); 3215 3216 // Return the result 3217 return floor($arguments); 3218 } 3219 3220 /** 3221 * Handles the XPath function ceiling. 3222 * 3223 * This method handles the XPath function ceiling. 3224 * 3225 * @access private 3226 * @author Michael P. Mehl <mpm@phpxml.org> 3227 * @param string $node Full path of the node on which the function 3228 * should be processed. 3229 * @param string $arguments String containing the arguments that were 3230 * passed to the function. 3231 * @return mixed Depending on the type of function being processed this 3232 * method returns different types. 3233 * @see evaluate() 3234 */ 3235 function handle_function_ceiling ( $node, $arguments ) 3236 { 3237 // Trim the arguments. 3238 $arguments = trim($arguments); 3239 3240 // Convert the arguments to a number. 3241 $arguments = doubleval($arguments); 3242 3243 // Return the result 3244 return ceil($arguments); 3245 } 3246 3247 /** 3248 * Handles the XPath function round. 3249 * 3250 * This method handles the XPath function round. 3251 * 3252 * @access private 3253 * @author Michael P. Mehl <mpm@phpxml.org> 3254 * @param string $node Full path of the node on which the function 3255 * should be processed. 3256 * @param string $arguments String containing the arguments that were 3257 * passed to the function. 3258 * @return mixed Depending on the type of function being processed this 3259 * method returns different types. 3260 * @see evaluate() 3261 */ 3262 function handle_function_round ( $node, $arguments ) 3263 { 3264 // Trim the arguments. 3265 $arguments = trim($arguments); 3266 3267 // Convert the arguments to a number. 3268 $arguments = doubleval($arguments); 3269 3270 // Return the result 3271 return round($arguments); 3272 } 3273 3274 /** 3275 * Handles the XPath function text. 3276 * 3277 * This method handles the XPath function text. 3278 * 3279 * @access private 3280 * @author Michael P. Mehl <mpm@phpxml.org> 3281 * @param string $node Full path of the node on which the function 3282 * should be processed. 3283 * @param string $arguments String containing the arguments that were 3284 * passed to the function. 3285 * @return mixed Depending on the type of function being processed this 3286 * method returns different types. 3287 * @see evaluate() 3288 */ 3289 function handle_function_text ( $node, $arguments ) 3290 { 3291 // Return the character data of the node. 3292 return $this->nodes[$node]["text"]; 3293 } 3294 3295 /** 3296 * Retrieves a substring before a delimiter. 3297 * 3298 * This method retrieves everything from a string before a given delimiter, 3299 * not including the delimiter. 3300 * 3301 * @access private 3302 * @author Michael P. Mehl <mpm@phpxml.org> 3303 * @param string $string String, from which the substring should be 3304 * extracted. 3305 * @param string $delimiter String containing the delimiter to use. 3306 * @return string Substring from the original string before the 3307 * delimiter. 3308 * @see afterstr() 3309 */ 3310 function prestr ( $string, $delimiter ) 3311 { 3312 // Return the substring. 3313 return substr($string, 0, strlen($string) - strlen(strstr($string, 3314 "$delimiter"))); 3315 } 3316 3317 /** 3318 * Retrieves a substring after a delimiter. 3319 * 3320 * This method retrieves everything from a string after a given delimiter, 3321 * not including the delimiter. 3322 * 3323 * @access private 3324 * @author Michael P. Mehl <mpm@phpxml.org> 3325 * @param string $string String, from which the substring should be 3326 * extracted. 3327 * @param string $delimiter String containing the delimiter to use. 3328 * @return string Substring from the original string after the 3329 * delimiter. 3330 * @see prestr() 3331 */ 3332 function afterstr ( $string, $delimiter ) 3333 { 3334 // Return the substring. 3335 return substr($string, 3336 strpos($string, $delimiter) + strlen($delimiter)); 3337 } 3338 3339 /** 3340 * Displays an error message. 3341 * 3342 * This method displays an error messages and stops the execution of the 3343 * script. This method is called exactly in the same way as the printf 3344 * function. The first argument contains the message and additional 3345 * arguments of various types may be passed to this method to be inserted 3346 * into the message. 3347 * 3348 * @access private 3349 * @author Michael P. Mehl <mpm@phpxml.org> 3350 * @param string $message Error message to be displayed. 3351 */ 3352 function display_error ( $message ) 3353 { 3354 // Check whether more than one argument was given. 3355 if ( func_num_args() > 1 ) 3356 { 3357 // Read all arguments. 3358 $arguments = func_get_args(); 3359 3360 // Create a new string for the inserting command. 3361 $command = "\$message = sprintf(\$message, "; 3362 3363 // Run through the array of arguments. 3364 for ( $i = 1; $i < sizeof($arguments); $i++ ) 3365 { 3366 // Add the number of the argument to the command. 3367 $command .= "\$arguments[".$i."], "; 3368 } 3369 3370 // Replace the last separator. 3371 $command = eregi_replace(", $", ");", $command); 3372 3373 // Execute the command. 3374 eval($command); 3375 } 3376 3377 // Display the error message. 3378 echo "<b>phpXML error:</b> ".$message; 3379 3380 // End the execution of this script. 3381 exit; 3382 } 3383 } 3384 3385 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |