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

Documentation generated on Mon, 11 Mar 2019 10:16:51 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.