Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
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 // | Authors: Bernd Römer <berndr@bonn.edu> |
16 // | Sebastian Bergmann <sb@sebastian-bergmann.de> |
17 // | Christian Kühn <ck@chkuehn.de> (escape xml entities) |
18 // | Michele Manzato <michele.manzato@verona.miz.it> |
19 // +----------------------------------------------------------------------+
20 //
21 // $Id: Node.php,v 1.5 2005/07/26 00:53:50 mmcintyre Exp $
22 //
23 
39  var $attributes;
40 
47  var $children;
48 
55  var $content;
56 
63  var $name;
64 
72  var $namespaces = array();
73 
80  var $error = null;
81 
88  var $use_cdata_section = null;
89 
90 
99  function XML_Tree_Node($name, $content = '', $attributes = array(), $lineno = null, $use_cdata_section = null)
100  {
101  $check_name = XML_Tree::isValidName($name, 'element');
102  if (PEAR::isError($check_name)) {
103  $this->error =& $check_name;
104  return;
105  }
106 
107  if (!is_array($attributes)) {
108  $attributes = array();
109  }
110 
111  foreach ($attributes as $attribute_name => $value) {
112  $error = XML_Tree::isValidName($attribute_name, 'Attribute');
113  if (PEAR::isError($error)) {
114  $this->error =& $error;
115  return;
116  }
117  }
118  $this->name = $name;
119  $this->setContent($content, $use_cdata_section);
120  $this->attributes = $attributes;
121  $this->children = array();
122  $this->lineno = $lineno;
123  }
124 
138  function &addChild($child, $content = '', $attributes = array(), $lineno = null, $use_cdata_section = null)
139  {
140  $index = sizeof($this->children);
141 
142  if (is_object($child)) {
143  if (strtolower(get_class($child)) == 'xml_tree_node') {
144  $this->children[$index] = $child;
145  }
146 
147  if (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
148  $this->children[$index] = $child->root->getElement();
149  }
150  } else {
151  $node = new XML_Tree_Node($child, $content, $attributes, $lineno, $use_cdata_section);
152  if (PEAR::isError($node->error)) {
153  return $node->error;
154  }
155 
156  $this->children[$index] = $node;
157  }
158 
159  return $this->children[$index];
160  }
161 
170  function &cloneNode()
171  {
172  $clone = new XML_Tree_Node($this->name,$this->content,$this->attributes);
173 
174  $max_child=count($this->children);
175  for($i=0;$i<$max_child;$i++) {
176  $clone->children[]=$this->children[$i]->cloneNode();
177  }
178 
179  /* for future use....
180  // clone all other vars
181  $temp=get_object_vars($this);
182  foreach($temp as $varname => $value)
183  if (!in_array($varname,array('name','content','attributes','children')))
184  $clone->$varname=$value;
185  */
186 
187  return $clone;
188  }
189 
209  function &insertChild($path,$pos,&$child, $content = '', $attributes = array())
210  {
211  $parent =& $this->getNodeAt($path);
212  if (PEAR::isError($parent)) {
213  // $path was not found
214  return $parent;
215  } elseif ($parent != $this) {
216  // Insert at the node found
217  return $parent->insertChild(null, $pos, $child, $content, $attributes);
218  }
219 
220  if (($pos < -count($this->children)) || ($pos > count($this->children))) {
221  return new PEAR_Error("Invalid insert position.");
222  }
223 
224  if (is_object($child)) { // child is an object
225  // insert a single node
226  if (strtolower(get_class($child)) == 'xml_tree_node') {
227  array_splice($this->children, $pos, 0, 'dummy');
228  if ($pos < 0) {
229  $pos = count($this->children) + $pos - 1;
230  }
231  $this->children[$pos] = &$child;
232  // insert a tree i.e insert root-element of tree
233  } elseif (strtolower(get_class($child)) == 'xml_tree' && isset($child->root)) {
234  array_splice($this->children, $pos, 0, 'dummy');
235  if ($pos < 0) {
236  $pos = count($this->children) + $pos - 1;
237  }
238  $this->children[$pos] = $child->root;
239  } else {
240  return new PEAR_Error("Bad node (must be a XML_Tree or an XML_Tree_Node)");
241  }
242  } else { // child offered is a string
243  array_splice($this->children, $pos, 0, 'dummy');
244  if ($pos < 0) {
245  $pos = count($this->children) + $pos - 1;
246  }
247  $this->children[$pos] = new XML_Tree_Node($child, $content, $attributes);
248  }
249  return $this;
250  }
251 
263  function &removeChild($pos)
264  {
265  if (($pos < -count($this->children)) || ($pos >= count($this->children))) {
266  return new PEAR_Error("Invalid remove position.");
267  }
268 
269  // Using array_splice() instead of a simple unset() to maintain index-integrity
270  return array_splice($this->children, $pos, 1);
271  }
272 
282  function registerName($name, $path) {
283  $this->namespace[$name] = $path;
284  }
285 
294  function &get($use_cdata_section = false)
295  {
296  static $deep = -1;
297  static $do_ident = true;
298  $deep++;
299  $empty = false;
300  $ident = str_repeat(' ', $deep);
301  if ($this->name !== null) {
302  if ($do_ident) {
303  $out = $ident . '<' . $this->name;
304  } else {
305  $out = '<' . $this->name;
306  }
307  foreach ($this->attributes as $name => $value) {
308  $out .= ' ' . $name . '="' . $value . '"';
309  }
310 
311  if (isset($this->namespace) && (is_array($this->namespace))) {
312  foreach ($this->namespace as $qualifier => $uri) {
313  if ($qualifier == '') {
314  $out .= " xmlns='$uri'";
315  } else {
316  $out .= " xmlns:$qualifier='$uri'";
317  }
318  }
319  }
320 
321  if ($this->content == '' && sizeof($this->children) === 0 && $deep != 0) {
322  $out .= ' />';
323  $empty = true;
324  } else {
325  $out .= '>';
326  if ($this->use_cdata_section == true || ($use_cdata_section == true && $this->use_cdata_section !== false)) {
327  if (trim($this->content) != '') {
328  $out .= '<![CDATA[' .$this->content. ']]>';
329  }
330  } else {
331  if (trim($this->content) != '') {
332  $out .= $this->content;
333  }
334  }
335  }
336 
337  if (sizeof($this->children) > 0) {
338  $out .= "\n";
339  foreach ($this->children as $child) {
340  $out .= $child->get($use_cdata_section);
341  }
342  } else {
343  $ident = '';
344  }
345 
346  if ($do_ident && $empty != true) {
347  $out .= $ident . '</' . $this->name . ">\n";
348  } elseif ($empty != true) {
349  $out .= '</' . $this->name . '>';
350  }
351  $do_ident = true;
352  } else {
353  if ($this->use_cdata_section == true || ($use_cdata_section == true && $this->use_cdata_section !== false)) {
354  if (trim($this->content) != '') {
355  $out = $ident . '<![CDATA[' .$this->content. ']]>' . "\n";
356  }
357  } else {
358  if (trim($this->content) != '') {
359  $out = $ident . $this->content . "\n";
360  }
361  }
362  }
363  $deep--;
364  return $out;
365  }
366 
376  function getAttribute($name)
377  {
378  if (isset($this->attributes[$name])) {
379  return $this->attributes[$name];
380  }
381  return null;
382  }
383 
393  function setAttribute($name, $value = '')
394  {
395  $this->attributes[$name] = $value;
396  }
397 
406  function unsetAttribute($name)
407  {
408  if (isset($this->attributes[$name])) {
409  unset($this->attributes[$name]);
410  }
411  }
412 
421  function setContent($content, $use_cdata_section = null)
422  {
423  $this->use_cdata_section = $use_cdata_section;
424 
425  if ($use_cdata_section == true) {
426  $this->content = $content;
427  } else {
428  $this->content = $this->encodeXmlEntities($content);
429  }
430  }
431 
444  function &getElement($path)
445  {
446  if (!is_array($path)) {
447  $path = array($path);
448  }
449  if (sizeof($path) == 0) {
450  return $this;
451  }
452 
453  $path1 = $path;
454  $next = array_shift($path1);
455  if (isset($this->children[$next])) {
456  $x =& $this->children[$next]->getElement($path1);
457  if (!PEAR::isError($x)) {
458  return $x;
459  }
460  }
461 
462  return new PEAR_Error("Bad path to node: [".implode('-', $path)."]");
463  }
464 
480  function &getNodeAt($path)
481  {
482  if (is_string($path))
483  $path = explode("/", $path);
484 
485  if (sizeof($path) == 0) {
486  return $this;
487  }
488 
489  $path1 = $path;
490  $next = array_shift($path1);
491 
492  // Get the first children of this node whose name is '$next'
493  $child = null;
494  for ($i = 0; $i < count($this->children); $i++) {
495  if ($this->children[$i]->name == $next) {
496  $child =& $this->children[$i];
497  break;
498  }
499  }
500  if (!is_null($child)) {
501  $x =& $child->getNodeAt($path1);
502  if (!PEAR::isError($x)) {
503  return $x;
504  }
505  }
506 
507  // No node with that name found
508  return new PEAR_Error("Bad path to node: [".implode('/', $path)."]");
509  }
510 
520  function encodeXmlEntities($xml)
521  {
522  $xml = str_replace(array('ü', 'Ü', 'ö',
523  'Ö', 'ä', 'Ä',
524  'ß',
525  //'<', '>',
526  // '"', '\''
527  ),
528  array('&#252;', '&#220;', '&#246;',
529  '&#214;', '&#228;', '&#196;',
530  '&#223;',
531  //'&lt;', '&gt;',
532  // '&quot;', '&apos;'
533  ),
534  $xml
535  );
536 
537  $xml = preg_replace(array("/\&([a-z\d\#]+)\;/i",
538  "/\&/",
539  "/\#\|\|([a-z\d\#]+)\|\|\#/i",
540  "/([^a-zA-Z\d\s<>\&\;\.\:\=\"\-\/\%\?\!\'\(\)\[\]\{\}\$\#\+\,\@_])/e"
541  ),
542  array("#||\\1||#",
543  "&amp;",
544  "&\\1;",
545  "'&#'.ord('\\1').';'"
546  ),
547  $xml
548  );
549 
550  return $xml;
551  }
552 
562  function decodeXmlEntities($xml)
563  {
564  static $trans_tbl = null;
565  if (!$trans_tbl) {
566  $trans_tbl = get_html_translation_table(HTML_ENTITIES);
567  $trans_tbl = array_flip($trans_tbl);
568  }
569  for ($i = 1; $i <= 255; $i++) {
570  $ent = sprintf("&#%03d;", $i);
571  $ch = chr($i);
572  $xml = str_replace($ent, $ch, $xml);
573  }
574 
575  return strtr($xml, $trans_tbl);
576  }
577 
578 
585  function dump() {
586  echo $this->get();
587  }
588 }
589 ?>