XML_Tree
[ class tree: XML_Tree ] [ index: XML_Tree ] [ all elements ]

Source for file Node.php

Documentation is available at Node.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: XML_Tree                                                     |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1997-2003 The PHP Group                                |
  6. // +----------------------------------------------------------------------+
  7. // | This source file is subject to version 2.02 of the PHP license,      |
  8. // | that is bundled with this package in the file LICENSE, and is        |
  9. // | available at through the world-wide-web at                           |
  10. // | http://www.php.net/license/2_02.txt.                                 |
  11. // | If you did not receive a copy of the PHP license and are unable to   |
  12. // | obtain it through the world-wide-web, please send a note to          |
  13. // | license@php.net so we can mail you a copy immediately.               |
  14. // +----------------------------------------------------------------------+
  15. // |          Sebastian Bergmann <sb@sebastian-bergmann.de>               |
  16. // |          Michele Manzato <michele.manzato@verona.miz.it>             |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Node.php 288859 2009-09-27 04:46:10Z clockwerx $
  20. //
  21.  
  22. /**
  23.  * PEAR::XML_Tree_Node
  24.  *
  25.  * @author
  26.  * @package XML_Tree
  27.  * @version 1.0  16-Aug-2001
  28.  */
  29.  
  30. class XML_Tree_Node {
  31.     /**
  32.      * Attributes of this node
  33.      *
  34.      * @var  array 
  35.      */
  36.  
  37.     var $attributes;
  38.  
  39.     /**
  40.      * Children of this node
  41.      *
  42.      * @var  array 
  43.      */
  44.  
  45.     var $children;
  46.  
  47.     /**
  48.      * Content (text) of this node
  49.      *
  50.      * @var  string 
  51.      */
  52.  
  53.     var $content;
  54.  
  55.     /**
  56.      * Name of the node
  57.      *
  58.      * @var  string 
  59.      */
  60.  
  61.     var $name;
  62.  
  63.     /**
  64.      * Namespaces for the node
  65.      *
  66.      * @var array 
  67.      */
  68.  
  69.  
  70.     var $namespaces = array();
  71.  
  72.     /**
  73.      * Stores PEAR_Error upon error
  74.      *
  75.      * @var object PEAR_Error 
  76.      */
  77.  
  78.     var $error = null;
  79.  
  80.     /**
  81.      * Whether to encapsulate the CDATA in a <![CDATA[]]> section
  82.      *
  83.      * @var boolean 
  84.      */
  85.  
  86.     var $use_cdata_section = null;
  87.  
  88.  
  89.     /**
  90.      * Constructor
  91.      *
  92.      * @param  string    name            Node name
  93.      * @param  string    content         Node content (text)
  94.      * @param  array     attributes      Attribute-hash for the node
  95.      */
  96.  
  97.     function XML_Tree_Node($name$content ''$attributes = array()$lineno = null$use_cdata_section = null)
  98.     {
  99.         $check_name XML_Tree::isValidName($name'element');
  100.         if (PEAR::isError($check_name)) {
  101.             $this->error =$check_name;
  102.             return;
  103.         }
  104.         
  105.         if (!is_array($attributes)) {
  106.             $attributes = array();
  107.         }
  108.         
  109.         foreach ($attributes as $attribute_name => $value{
  110.             $error XML_Tree::isValidName($attribute_name'Attribute');
  111.             if (PEAR::isError($error)) {
  112.                 $this->error =$error;
  113.                 return;
  114.             }
  115.         }
  116.         $this->name = $name;
  117.         $this->setContent($content$use_cdata_section);
  118.         $this->attributes = $attributes;
  119.         $this->children   = array();
  120.         $this->lineno     $lineno;
  121.     }
  122.  
  123.     /**
  124.      * Append a child node to this node, after all other nodes
  125.      *
  126.      * @param mixed      child           Child to insert (XML_Tree or XML_Tree_Node),
  127.      *                                    or name of child node
  128.      * @param string     content         Content (text) for the new node (only if
  129.      *                                    $child is the node name)
  130.      * @param array      attributes      Attribute-hash for new node
  131.      *
  132.      * @return object  reference to new child node
  133.      * @access public
  134.      */
  135.  
  136.     function &addChild($child$content ''$attributes = array()$lineno = null$use_cdata_section = null)
  137.     {
  138.         $index sizeof($this->children);
  139.  
  140.         if (is_object($child)) {
  141.             if (strtolower(get_class($child)) == 'xml_tree_node'{
  142.                 $this->children[$index$child;
  143.             }
  144.  
  145.             if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
  146.                 $this->children[$index$child->root->getElement();
  147.             }
  148.         else {
  149.             $node = new XML_Tree_Node($child$content$attributes$lineno$use_cdata_section);
  150.             if (PEAR::isError($node->error)) {
  151.                 return $node->error;
  152.             }
  153.  
  154.             $this->children[$index$node;
  155.         }
  156.  
  157.         return $this->children[$index];
  158.     }
  159.  
  160.     /**
  161.      * Get a copy of this node by clone this node and all of its children,
  162.      * recursively.
  163.      *
  164.      * @return object    Reference to the cloned copy.
  165.      * @access public
  166.      */
  167.  
  168.     function &cloneNode()
  169.     {
  170.         $clone = new XML_Tree_Node($this->name,$this->content,$this->attributes);
  171.  
  172.         $max_child=count($this->children);
  173.         for($i=0;$i<$max_child;$i++{
  174.             $clone->children[]=$this->children[$i]->cloneNode();
  175.         }
  176.  
  177.         /* for future use....
  178.         // clone all other vars
  179.         $temp=get_object_vars($this);
  180.         foreach($temp as $varname => $value)
  181.         if (!in_array($varname,array('name','content','attributes','children')))
  182.         $clone->$varname=$value;
  183.          */
  184.  
  185.         return $clone;
  186.     }
  187.  
  188.     /**
  189.      * Inserts child ($child) to a specified child-position ($pos)
  190.      *
  191.      * @param mixed      path            Path to parent node to add child (see getNodeAt()
  192.      *                                    for format). If null child is inserted in the
  193.      *                                    current node.
  194.      * @param integer    pos             Position where to insert the new child.
  195.      *                                    0 < means |$pos| elements before the end,
  196.      *                                    e.g. -1 appends as last child.
  197.      * @param mixed      child           Child to insert (XML_Tree or XML_Tree_Node),
  198.      *                                    or name of child node
  199.      * @param string     content         Content (text) for the new node (only if
  200.      *                                    $child is the node name)
  201.      * @param array      attributes      Attribute-hash for new node
  202.      *
  203.      * @return Reference to the newly inserted node, or PEAR_Error upon insertion error.
  204.      * @access public
  205.      */
  206.  
  207.     function &insertChild($path,$pos,&$child$content ''$attributes = array())
  208.     {
  209.         $parent =$this->getNodeAt($path);
  210.         if (PEAR::isError($parent)) {
  211.             // $path was not found
  212.             return $parent;
  213.         elseif ($parent != $this{
  214.             // Insert at the node found
  215.             return $parent->insertChild(null$pos$child$content$attributes);
  216.         }
  217.  
  218.         if (($pos < -count($this->children)) || ($pos count($this->children))) {
  219.             return new PEAR_Error("Invalid insert position.");
  220.         }
  221.  
  222.         if (is_object($child)) // child is an object
  223.         // insert a single node
  224.         if (strtolower(get_class($child)) == 'xml_tree_node'{
  225.             array_splice($this->children$pos0'dummy');
  226.             if ($pos < 0{
  227.                 $pos count($this->children$pos - 1;
  228.             }
  229.             $this->children[$pos&$child;
  230.             // insert a tree i.e insert root-element of tree
  231.         elseif (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
  232.             array_splice($this->children$pos0'dummy');
  233.             if ($pos < 0{
  234.                 $pos count($this->children$pos - 1;
  235.             }
  236.             $this->children[$pos$child->root;
  237.         else {
  238.             return new PEAR_Error("Bad node (must be a XML_Tree or an XML_Tree_Node)");
  239.         }
  240.         else // child offered is a string
  241.         array_splice($this->children$pos0'dummy');
  242.         if ($pos < 0{
  243.             $pos count($this->children$pos - 1;
  244.         }
  245.         $this->children[$pos= new XML_Tree_Node($child$content$attributes);
  246.         }
  247.         return $this;
  248.     }
  249.  
  250.     /**
  251.      * Removes child at a given position
  252.      *
  253.      * @param    integer     pos     position of child to remove in children-list.
  254.      *                                0 < means |$pos| elements before the end,
  255.      *                                e.g. -1 removes the last child.
  256.      *
  257.      * @return mixed     The removed node, or PEAR_Error upon removal error.
  258.      * @access public
  259.      */
  260.  
  261.     function &removeChild($pos)
  262.     {
  263.         if (($pos < -count($this->children)) || ($pos >= count($this->children))) {
  264.             return new PEAR_Error("Invalid remove position.");
  265.         }
  266.  
  267.         // Using array_splice() instead of a simple unset() to maintain index-integrity
  268.         return array_splice($this->children$pos1);
  269.     }
  270.  
  271.     /**
  272.      * Register a namespace.
  273.      *
  274.      * @param  string  $name namespace
  275.      * @param  string  $path path
  276.      *
  277.      * @access public
  278.      */
  279.  
  280.     function registerName($name$path{
  281.         $this->namespace[$name$path;
  282.     }
  283.  
  284.     /**
  285.      * Returns text representation of this node.
  286.      *
  287.      * @return  string   text (xml) representation of this node. Each tag is
  288.      *                    indented according to its level.
  289.      * @access public
  290.      */
  291.  
  292.     function &get($use_cdata_section = false)
  293.     {
  294.         static $deep = -1;
  295.         static $do_ident = true;
  296.         $deep++;
  297.         $empty = false;
  298.         $ident str_repeat('  '$deep);
  299.         if ($this->name !== null{
  300.             if ($do_ident{
  301.                 $out $ident '<' $this->name;
  302.             else {
  303.                 $out '<' $this->name;
  304.             }
  305.             foreach ($this->attributes as $name => $value{
  306.                 $out .= ' ' $name '="' $value '"';
  307.             }
  308.  
  309.             if (isset($this->namespace&& (is_array($this->namespace))) {
  310.                 foreach ($this->namespace as $qualifier => $uri{
  311.                     if ($qualifier == ''{
  312.                         $out .= " xmlns='$uri'";
  313.                     else {
  314.                         $out .= " xmlns:$qualifier='$uri'";
  315.                     }
  316.                 }
  317.             }
  318.  
  319.             if ($this->content == '' && sizeof($this->children=== 0 && $deep != 0{
  320.                 $out .= ' />';
  321.                 $empty = true;
  322.             else {
  323.                 $out .= '>';
  324.                 if ($this->use_cdata_section == true || ($use_cdata_section == true && $this->use_cdata_section !== false)) {
  325.                     if (trim($this->content!= ''{
  326.                         $out .= '<![CDATA[' .$this->content']]>';
  327.                     }
  328.                     else {
  329.                     if (trim($this->content!= ''{
  330.                         $out .= $this->content;
  331.                     }
  332.                 }
  333.             }
  334.  
  335.             if (sizeof($this->children> 0{
  336.                 $out .= "\n";
  337.                 foreach ($this->children as $child{
  338.                     $out .= $child->get($use_cdata_section);
  339.                 }
  340.             else {
  341.                 $ident '';
  342.             }
  343.  
  344.             if ($do_ident && $empty != true{
  345.                 $out .= $ident '</' $this->name . ">\n";
  346.             elseif ($empty != true{
  347.                 $out .= '</' $this->name . '>';
  348.             }
  349.             $do_ident = true;
  350.         else {
  351.             if ($this->use_cdata_section == true || ($use_cdata_section == true && $this->use_cdata_section !== false)) {
  352.                 if (trim($this->content!= ''{
  353.                     $out $ident '<![CDATA[' .$this->content']]>' "\n";
  354.                 }
  355.             else {
  356.                 if (trim($this->content!= ''{
  357.                     $out $ident $this->content . "\n";
  358.                 }
  359.             }
  360.         }
  361.         $deep--;
  362.         return $out;
  363.     }
  364.  
  365.     /**
  366.      * Get an attribute by its name.
  367.      *
  368.      * @param  string  $name     Name of attribute to retrieve
  369.      *
  370.      * @return string  attribute, or null if attribute is unset.
  371.      * @access public
  372.      */
  373.  
  374.     function getAttribute($name)
  375.     {
  376.         if (isset($this->attributes[$name])) {
  377.             return $this->attributes[$name];
  378.         }
  379.         return null;
  380.     }
  381.  
  382.     /**
  383.      * Sets an attribute for this node.
  384.      *
  385.      * @param  string    name        Name of attribute to set
  386.      * @param  string    value       Value of attribute
  387.      *
  388.      * @access public
  389.      */
  390.  
  391.     function setAttribute($name$value '')
  392.     {
  393.         $this->attributes[$name$value;
  394.     }
  395.  
  396.     /**
  397.      * Unsets an attribute of this node.
  398.      *
  399.      * @param  string  $name     Name of attribute to unset
  400.      *
  401.      * @access public
  402.      */
  403.  
  404.     function unsetAttribute($name)
  405.     {
  406.         if (isset($this->attributes[$name])) {
  407.             unset($this->attributes[$name]);
  408.         }
  409.     }
  410.  
  411.     /**
  412.      * Sets the content for this node.
  413.      *
  414.      * @param  string    content     Node content to assign
  415.      *
  416.      * @access public
  417.      */
  418.  
  419.     function setContent($content$use_cdata_section = null)
  420.     {
  421.         $this->use_cdata_section = $use_cdata_section;
  422.  
  423.         if ($use_cdata_section == true{
  424.             $this->content = $content;
  425.         else {
  426.             $this->content = $this->encodeXmlEntities($content);
  427.         }
  428.     }
  429.  
  430.     /**
  431.      * Gets an element by its 'path'.
  432.      *
  433.      * @param  array     path    path to element: sequence of indexes to the
  434.      *                            children. E.g. array(1, 2, 3) means "third
  435.      *                            child of second child of first child" of the node.
  436.      *
  437.      * @return object    reference to element found, or PEAR_Error if node can't
  438.      *                    be found.
  439.      * @access public
  440.      */
  441.  
  442.     function &getElement($path)
  443.     {
  444.         if (!is_array($path)) {
  445.             $path = array($path);
  446.         }
  447.         if (sizeof($path== 0{
  448.             return $this;
  449.         }
  450.  
  451.         $path1 $path;
  452.         $next array_shift($path1);
  453.         if (isset($this->children[$next])) {
  454.             $x =$this->children[$next]->getElement($path1);
  455.             if (!PEAR::isError($x)) {
  456.                 return $x;
  457.             }
  458.         }
  459.  
  460.         return new PEAR_Error("Bad path to node: [".implode('-'$path)."]");
  461.     }
  462.  
  463.     /**
  464.      * Get a reference to a node by its 'path'.
  465.      *
  466.      * @param  mixed     path    Path to node. Can be either a string (slash-separated
  467.      *    children names) or an array (sequence of children names) both
  468.      *                            starting from this node. The first name in sequence
  469.      *    is a child name, not the name of this node.
  470.      *
  471.      * @return object    Reference to the XML_Tree_Node found, or PEAR_Error if
  472.      *                    the path does not match any node. Note that if more than
  473.      *                    one element matches then only the first matching node is
  474.      *                    returned.
  475.      * @access public
  476.      */
  477.  
  478.     function &getNodeAt($path)
  479.     {
  480.         if (is_string($path))
  481.             $path explode("/"$path);
  482.  
  483.         if (sizeof($path== 0{
  484.             return $this;
  485.         }
  486.  
  487.         $path1 $path;
  488.         $next array_shift($path1);
  489.  
  490.         // Get the first children of this node whose name is '$next'
  491.         $child = null;
  492.         for ($i = 0; $i count($this->children)$i++{
  493.             if ($this->children[$i]->name == $next{
  494.                 $child =$this->children[$i];
  495.                 break;
  496.             }
  497.         }
  498.         if (!is_null($child)) {
  499.             $x =$child->getNodeAt($path1);
  500.             if (!PEAR::isError($x)) {
  501.                 return $x;
  502.             }
  503.         }
  504.  
  505.         // No node with that name found
  506.         return new PEAR_Error("Bad path to node: [".implode('/'$path)."]");
  507.     }
  508.  
  509.     /**
  510.      * Escape XML entities.
  511.      *
  512.      * @param   string  xml      Text string to escape.
  513.      *
  514.      * @return  string  xml
  515.      * @access  public
  516.      */
  517.  
  518.     function encodeXmlEntities($xml)
  519.     {
  520.         $xml str_replace(array(,
  521.                                  ,
  522.                                  '<''>',
  523.                                  '"''\''
  524.                                 ),
  525.                            array('&#252;''&#220;''&#246;',
  526.                                  '&#214;''&#228;''&#196;',
  527.                                   '&#223;''&lt;''&gt;',
  528.                                   '&quot;''&apos;'
  529.                                 ),
  530.                            $xml
  531.                           );
  532.  
  533.         $xml preg_replace(array("/\&([a-z\d\#]+)\;/i",
  534.                                   "/\&/",
  535.                                   "/\#\|\|([a-z\d\#]+)\|\|\#/i",
  536.                                   "/([^a-zA-Z\d\s\<\>\&\;\.\:\=\"\-\/\%\?\!\'\(\)\[\]\{\}\$\#\+\,\@_])/e"
  537.                                  ),
  538.                             array("#||\\1||#",
  539.                                   "&amp;",
  540.                                   "&\\1;",
  541.                                   "'&#'.ord('\\1').';'"
  542.                                  ),
  543.                             $xml
  544.                            );
  545.  
  546.         return $xml;
  547.     }
  548.  
  549.     /**
  550.      * Decode XML entities in a text string.
  551.      *
  552.      * @param   string  xml  Text to decode
  553.      *
  554.      * @return  string  Decoded text
  555.      * @access  public
  556.      */
  557.  
  558.     function decodeXmlEntities($xml)
  559.     {
  560.         static $trans_tbl = null;
  561.         if (!$trans_tbl{
  562.             $trans_tbl = get_html_translation_table(HTML_ENTITIES);
  563.             $trans_tbl = array_flip($trans_tbl);
  564.         }
  565.         for ($i = 1; $i <= 255; $i++{
  566.             $ent sprintf("&#%03d;"$i);
  567.             $ch chr($i);
  568.             $xml str_replace($ent$ch$xml);
  569.         }
  570.  
  571.         return strtr($xml$trans_tbl);
  572.     }
  573.  
  574.  
  575.     /**
  576.      * Print text representation of XML_Tree_Node.
  577.      *
  578.      * @access  public
  579.      */
  580.  
  581.     function dump({
  582.         echo $this->get();
  583.     }
  584. }
  585. ?>

Documentation generated on Mon, 11 Mar 2019 15:34:45 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.