phpDocumentor SpoolTemplate
[ Back ] [ class tree: SpoolTemplate ] [ index: SpoolTemplate ] [ all elements ]

Source for file CXml2Array.php

Documentation is available at CXml2Array.php

  1. <?php
  2. /*
  3. * CXml2Array.php
  4. * $Header: d:\cvs/classistd/sptpl/CXml2Array.php,v 2.9 2005/03/17 12:47:01 Darvin Exp $
  5. *
  6. * Class to convert an XML file into array
  7. *
  8. * Copyright (C) 2003-2005 Andrioli Darvin <darvin at andrioli.com>
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2 of the License, or (at your option) any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24.  
  25. class CXml2Array
  26. {
  27. /**
  28. * Array containg the file XML
  29. * structure:
  30. * ['text'] -> text inside the tag
  31. * ['attrib'][attribname] -> tag's attribute
  32. * ['child'][] -> child tag information. It holds many child with the
  33. * same name
  34. *
  35. * @var array
  36. */
  37. var $TheArray;
  38.  
  39. /**
  40. * Temporary arrays
  41. */
  42. var $tmpAttrib;
  43. var $tmpTag;
  44.  
  45. var $AttribFirstTime;
  46. var $TagFirstTime;
  47. var $IntTmpTag;
  48. /**
  49. * Which PHP extension the module uses to parse the XML data
  50. * @var string
  51. * @see _WhichExtension()
  52. */
  53. var $Extension;
  54. /**
  55. * Class initializer
  56. * @param mixed object DOM XML or array returned by GetTag
  57. * @access public
  58. * @see GetTag()
  59. */
  60. function CXml2Array($node='')
  61. {
  62. $this->Extension=$this->_WhichExtension();
  63. if(!is_string($node))
  64. {
  65. //
  66. if(is_array($node))
  67. $this->LoadFromArray($node);
  68. else
  69. {
  70. if(is_object($node))
  71. $this->TheArray=$this->Parse($node);
  72. else
  73. trigger_error('Invalid parameter',E_USER_ERROR);
  74. }
  75. $this->tmpAttrib=$this->TheArray['attrib'];
  76. $this->tmpTag=$this->TheArray['child'];
  77. $this->AttribFirstTime=true;
  78. $this->TagFirstTime=true;
  79. }
  80. }
  81.  
  82. /**
  83. * Load data from filename
  84. * @param string filename
  85. * @return bool true if the file is successfully parsed
  86. * @access public
  87. */
  88. function LoadFromFile($FileName)
  89. {
  90. if($this->Extension=='DOM')
  91. {
  92. $doc = new DOMDocument; // require zend.ze1_compatibility_mode = off
  93. if(!$doc->load(realpath($FileName)))
  94. trigger_error('Error parsing the file '.$FileName,E_USER_ERROR);
  95. $root=$doc->documentElement;
  96. }
  97. else
  98. {
  99. if(!$this->TplDom = domxml_open_file(realpath($FileName)))
  100. trigger_error('Error parsing the file '.$FileName,E_USER_ERROR);
  101. $root = $this->TplDom->document_element();
  102. }
  103. $this->TheArray=$this->Parse($root);
  104. $this->tmpAttrib=$this->TheArray['attrib'];
  105. $this->tmpTag=$this->TheArray['child'];
  106. $this->AttribFirstTime=true;
  107. $this->TagFirstTime=true;
  108. }
  109.  
  110. /**
  111. * Load data from xml string
  112. * @param string XML text
  113. * @return bool true if the file is successfully parsed
  114. * @access public
  115. */
  116. function LoadFromString($XmlStr)
  117. {
  118. if($this->Extension=='DOM')
  119. {
  120. $dom = new DOMDocument();
  121. $dom->loadXML($XmlStr);
  122. $root = $dom->documentElement;
  123. }
  124. else
  125. {
  126. if(!$dom = domxml_open_mem($XmlStr))
  127. trigger_error("Internal Error while creating standard font",E_USER_ERROR);
  128. $root = $dom->document_element();
  129. }
  130. $this->TheArray=$this->Parse($root);
  131. $this->tmpAttrib=$this->TheArray['attrib'];
  132. $this->tmpTag=$this->TheArray['child'];
  133. $this->AttribFirstTime=true;
  134. $this->TagFirstTime=true;
  135. }
  136.  
  137. /**
  138. * Evaluate which PHP extension the module should use to parse the XML data
  139. * PHP4 -> DOMXML
  140. * PHP5 -> DOM
  141. * @access private
  142. * @return string The extension name
  143. */
  144. function _WhichExtension()
  145. {
  146. return(($this->__php5())?'DOM':'DOMXML');
  147. }
  148.  
  149. /**
  150. * Return True if the current PHP version is 5
  151. * False if is PHP4
  152. * @return boolean
  153. * @access public
  154. */
  155. function __php5()
  156. {
  157. return((version_compare(phpversion(), "5.0.0", "<")==-1)?false:true);
  158. }
  159.  
  160. /**
  161. * Parse one XML node. With PHP4 it uses DOMXML extension, with PHP it
  162. * uses DOM extension.
  163. * @param object DOMXML/DOM
  164. * @param integer Nesting level
  165. * @access private
  166. */
  167. function Parse($Node,$level=0,$NodeName='')
  168. {
  169. if($this->Extension=='DOM')
  170. $ret=$this->ParseDOM($Node,$level,$NodeName);
  171. else
  172. $ret=$this->ParseDOMXML($Node,$level,$NodeName);
  173. return($ret);
  174. }
  175.  
  176. /**
  177. * Parse one XML node.
  178. * @param object DOMXML
  179. * @param integer Nesting level
  180. * @access private
  181. */
  182. function ParseDOMXML($Node,$level=0,$NodeName='')
  183. {
  184. $type=array( 1 =>'XML_ELEMENT_NODE',
  185. 2 =>'XML_ATTRIBUTE_NODE',
  186. 3 =>'XML_TEXT_NODE',
  187. 4 =>'XML_CDATA_SECTION_NODE',
  188. 5 =>'XML_ENTITY_REF_NODE',
  189. 6 =>'XML_ENTITY_NODE',
  190. 17 =>'XML_ENTITY_DECL_NODE'
  191. );
  192. // print_r($Node);
  193. $Text='';
  194. //$NodeName='';
  195. $Contents=array();
  196. $Attrib=array();
  197. // load the attribs
  198. $AttrTbl=$Node->attributes();
  199. if($AttrTbl) {
  200. // First I'm looking for the attrib Id
  201. foreach($AttrTbl as $Att)
  202. {
  203. $AttribName=strtolower($Att->name());
  204. $Attrib[$AttribName]=$Att->value();
  205. }
  206. }
  207. // childs parse
  208. $child = $Node->first_child();
  209. while($child) {
  210. //echo '<br>child:';
  211. // echo '<br>['.$level.']'.$type[$child->node_type()];
  212. switch($child->node_type())
  213. {
  214. case XML_ENTITY_REF_NODE :
  215. $ret=$this->Parse($child,$level+1);
  216. // var_dump($ret);
  217. foreach($ret['child'] as $key => $value)
  218. {
  219. $Contents[]=$value;
  220. }
  221. //return($ret);
  222. break;
  223. case XML_ENTITY_DECL_NODE :
  224. $ret=$this->Parse($child,$level+1);
  225. return($ret);
  226. break;
  227. case XML_TEXT_NODE:
  228. $Text.=rtrim($child->node_value());
  229. break;
  230. case XML_CDATA_SECTION_NODE:
  231. $Text.=rtrim($child->node_value());
  232. break;
  233. case XML_ELEMENT_NODE:
  234. $NName=strtolower($child->node_name());
  235. $Contents[]=$this->Parse($child,$level+1,$NName);
  236. break;
  237. } // switch node type
  238. $child = $child->next_sibling();
  239. }
  240. return(array('child' => $Contents,
  241. 'text' => $Text,
  242. 'attrib' => $Attrib,
  243. 'nodename' => $NodeName)
  244. );
  245. }
  246.  
  247. /**
  248. * Parse one XML node.DOM version (PHP5)
  249. * @param object DOM
  250. * @param integer Nesting level
  251. * @access private
  252. */
  253. function ParseDOM($Node,$level=0,$NodeName='')
  254. {
  255. $type=array( 1 =>'XML_ELEMENT_NODE',
  256. 2 =>'XML_ATTRIBUTE_NODE',
  257. 3 =>'XML_TEXT_NODE',
  258. 4 =>'XML_CDATA_SECTION_NODE',
  259. 5 =>'XML_ENTITY_REF_NODE',
  260. 6 =>'XML_ENTITY_NODE',
  261. 17 =>'XML_ENTITY_DECL_NODE'
  262. );
  263. // print_r($Node);
  264. $Text='';
  265. //$NodeName='';
  266. $Contents=array();
  267. $Attrib=array();
  268. // load the attribs
  269. $AttrTbl=$Node->attributes;
  270. if($AttrTbl) {
  271. // First I'm looking for the attrib Id
  272. foreach($AttrTbl as $Att)
  273. {
  274. $AttribName=strtolower($Att->name);
  275. $Attrib[$AttribName]=$Att->value;
  276. }
  277. }
  278. // childs parse
  279. $child = $Node->firstChild;
  280. while($child) {
  281. //echo '<br>child:';
  282. // echo '<br>['.$level.']'.$type[$child->node_type()];
  283. switch($child->nodeType)
  284. {
  285. case XML_ENTITY_REF_NODE :
  286. $ret=$this->Parse($child,$level+1);
  287. // var_dump($ret);
  288. foreach($ret['child'] as $key => $value)
  289. {
  290. //if(array_key_exists($key,$Contents))
  291. // {
  292. // $t=array_merge($Contents[$key],$value);
  293. // $Contents[$key]=$t;
  294. // }
  295. // else
  296. // {
  297. $Contents[]=$value;
  298. // }
  299. }
  300. //return($ret);
  301. break;
  302. case XML_ENTITY_DECL_NODE :
  303. $ret=$this->Parse($child,$level+1);
  304. return($ret);
  305. break;
  306. case XML_TEXT_NODE:
  307. $Text.=rtrim($child->nodeValue);
  308. break;
  309. case XML_CDATA_SECTION_NODE:
  310. $Text.=rtrim($child->nodeValue);
  311. //$Text.=ereg_replace(' ','&nbsp;',$passo1);
  312. //$Text.=htmlentities(trim($child->node_value()));
  313. break;
  314. case XML_ELEMENT_NODE:
  315. $NName=strtolower($child->nodeName);
  316. $Contents[]=$this->Parse($child,$level+1,$NName);
  317. break;
  318. } // switch node type
  319. $child = $child->nextSibling;
  320. }
  321. return(array('child' => $Contents,
  322. 'text' => $Text,
  323. 'attrib' => $Attrib,
  324. 'nodename' => $NodeName)
  325. );
  326. }
  327.  
  328. /**
  329. * Load the array from another array retrieved from this class.
  330. * It is usefull to apply the module's function to the deepest part of the
  331. * original array
  332. * @param array
  333. */
  334. function LoadFromArray($data)
  335. {
  336. $this->TheArray=$data;
  337. // if(!array_key_exists('attrib',$this->TheArray))
  338. // $this->TheArray['attrib']=array();
  339. if(!array_key_exists('text',$this->TheArray))
  340. $this->TheArray['text']='';
  341. }
  342.  
  343. /**
  344. * Dump the array contents in human format.
  345. * Usefull for debug purpose
  346. * @access public
  347. */
  348. function ArrayDump()
  349. {
  350. // var_dump($this->TheArray);
  351. //echo '<hr>';
  352. $this->_dump($this->TheArray);
  353. }
  354.  
  355. /**
  356. * Internal function used to dump the array
  357. * @param array data to dump
  358. * @param integer
  359. * @access private
  360. */
  361. function _dump($data,$level=0)
  362. {
  363. $ta=20;
  364. $c='.';
  365. echo str_repeat($c,$level*$ta).'[text]:'.$data['text'].'<br>';
  366. echo str_repeat($c,$level*$ta).'[nodename]:'.$data['nodename'].'<br>';
  367. echo str_repeat($c,$level*$ta).'[attrib]:'.'<br>';
  368. foreach($data['attrib'] as $key => $value)
  369. {
  370. echo str_repeat($c,$level*$ta).'.........['.$key.']:'.$value.'<br>';
  371. }
  372. echo str_repeat($c,$level*$ta).'[child]:'.'<br>';
  373. foreach($data['child'] as $key => $value)
  374. {
  375. //var_dump($data['tag']);
  376. echo str_repeat($c,$level*$ta).'.........['.$key.']:'.'<br>';
  377. // foreach($data['child'][$key] as $key1 => $value1)
  378. // {
  379. //var_dump($value1);
  380. // echo str_repeat($c,($level+1)*$ta-4).'['.$key1.']';
  381. $this->_dump($value,$level+1);
  382. // }
  383. }
  384. }
  385.  
  386.  
  387. /**********************************
  388. * Retrieve functions
  389. ************************************/
  390.  
  391. /**
  392. * Does exist the request tag? The function looks only if the tag exists
  393. * as child of the root element.
  394. * @param string
  395. * @return bool
  396. * @access public
  397. */
  398. function ExistTag($TagName)
  399. {
  400. $noItem=count($this->TheArray['child']);
  401. $Found=FALSE;
  402. for($i=0;$i<$noItem&&!$Found;$i++)
  403. {
  404. if($this->TheArray['child'][$i]['nodename']==$TagName)
  405. $Found=TRUE;
  406. }
  407. return($Found);
  408. }
  409.  
  410. /**
  411. * Does exist the request attribute? The function looks only if the attribute exists
  412. * as child of the root element.
  413. * @param string
  414. * @return bool
  415. * @access public
  416. */
  417. function ExistAttribute($AttribName)
  418. {
  419. return(array_key_exists($AttribName,$this->TheArray['attrib']));
  420. }
  421.  
  422. /**
  423. * Return the XML as array
  424. * @access public
  425. */
  426. function GetArray()
  427. {
  428. return($this->TheArray);
  429. }
  430.  
  431. /**
  432. * The function return all childs of the root element named $TagName
  433. * @param string
  434. * @return array
  435. * @access public
  436. */
  437. function GetTag($TagName)
  438. {
  439. $noItem=count($this->TheArray['child']);
  440. $ret=array();
  441. $Found=FALSE;
  442. for($i=0;$i<$noItem;$i++)
  443. {
  444. if($this->TheArray['child'][$i]['nodename']==$TagName)
  445. {
  446. $ret[]=$this->TheArray['child'][$i];
  447. $Found=TRUE;
  448. }
  449. }
  450.  
  451. if($Found)
  452. return($ret);
  453. else
  454. return(FALSE);
  455. }
  456.  
  457. /**
  458. * The function return all childs of the root element named $TagName
  459. * @param string
  460. * @return array
  461. * @access public
  462. */
  463. function GetTagPos($TagName,$Position=0)
  464. {
  465. $count=0;
  466. $noItem=count($this->TheArray['child']);
  467. for($i=0;$i<$noItem;$i++)
  468. {
  469. if($this->TheArray['child'][$i]['nodename']==$TagName)
  470. {
  471. if($count==$Position)
  472. return($this->TheArray['child'][$i]);
  473. $count++;
  474. }
  475. }
  476. return(FALSE);
  477. }
  478.  
  479. /**
  480. * The function return all childs of $TagName. Note $TagName should be a child of the
  481. * root element
  482. * @param string
  483. * @param integer Select from which child retrieve the information, if more child of
  484. * root element have the same name
  485. * @return array
  486. * @access public
  487. */
  488. function GetTagChilds($TagName,$Position=0)
  489. {
  490. $noItem=count($this->TheArray['child']);
  491. $count=0;
  492. for($i=0;$i<$noItem;$i++)
  493. {
  494. if($this->TheArray['child'][$i]['nodename']==$TagName)
  495. {
  496. if($count==$Position)
  497. return($this->TheArray['child'][$i]['child']);
  498. $count++;
  499. }
  500. }
  501. return(FALSE);
  502. }
  503.  
  504. /**
  505. * The function return all attributes of $TagName. Note $TagName should be a child of the
  506. * root element
  507. * @param string
  508. * @param integer Select from which child retrieve the information, if more child of
  509. * root element have the same name
  510. * @return array
  511. * @access public
  512. */
  513. function GetTagAttributes($TagName,$Position=0)
  514. {
  515. $noItem=count($this->TheArray['child']);
  516. $count=0;
  517. for($i=0;$i<$noItem;$i++)
  518. {
  519. if($this->TheArray['child'][$i]['nodename']==$TagName)
  520. {
  521. if($count==$Position)
  522. return($this->TheArray['child'][$i]['attrib']);
  523. $count++;
  524. }
  525. }
  526. return(FALSE);
  527. }
  528.  
  529. /**
  530. * Return value of the named attribute
  531. * @param string
  532. * @return string
  533. * @access public
  534. */
  535. function GetAttribute($AttribName)
  536. {
  537. if($this->ExistAttribute($AttribName))
  538. return($this->TheArray['attrib'][$AttribName]);
  539. else
  540. return(FALSE);
  541. }
  542.  
  543. /**
  544. * Return value of the root tag
  545. * @return string
  546. * @access public
  547. */
  548. function GetText()
  549. {
  550. return($this->TheArray['text']);
  551. }
  552.  
  553. /**
  554. * Return the name of the root tag
  555. * @return string
  556. * @access public
  557. */
  558. function GetNodeName()
  559. {
  560. return($this->TheArray['nodename']);
  561. }
  562.  
  563.  
  564. /**
  565. * The function iterate over attribute's array of the root element
  566. * @param bool Set to TRUE to reset the internal pointer
  567. * @return array
  568. * @access public
  569. */
  570. function EachAttribute($reset=FALSE)
  571. {
  572. // var_dump($this->TheArray);
  573. // var_dump($this->tmpAttrib);
  574. if(!is_array($this->tmpAttrib))
  575. return(FALSE);
  576. if($reset)
  577. {
  578. $this->AttribFirstTime=TRUE;
  579. return(TRUE);
  580. }
  581.  
  582. if($this->AttribFirstTime)
  583. {
  584. reset($this->tmpAttrib);
  585. $this->AttribFirstTime=false;
  586. }
  587. else
  588. if(!next($this->tmpAttrib))
  589. return(FALSE);
  590. $value=current($this->tmpAttrib);
  591. $key=key($this->tmpAttrib);
  592.  
  593. return(array($key,$value));
  594. }
  595.  
  596. /**
  597. * The function iterate over tag's array of the root element
  598. * Public method
  599. * @param bool Set to TRUE to reset the internal pointer
  600. * @return object CXml2Array
  601. * @access public
  602. * @see _ChildLoop()
  603. */
  604. function EachChild($reset=FALSE)
  605. {
  606. return($this->_ChildLoop($reset,TRUE));
  607. }
  608.  
  609. /**
  610. * The function iterate over tag's array of the root element
  611. * Public method
  612. * @param bool Set to TRUE to reset the internal pointer
  613. * @return array
  614. * @access public
  615. * @see _ChildLoop()
  616. */
  617. function EachChildArray($reset=FALSE)
  618. {
  619. return($this->_ChildLoop($reset,FALSE));
  620. }
  621.  
  622. /**
  623. * The function iterate over tag's array of the root element
  624. * @param bool Set to TRUE to reset the internal pointer (return TRUE)
  625. * @param bool Set to TRUE to return an object CXml2Array, o FALSE to return tha
  626. * child's value as array
  627. * @return object CXml2Array
  628. * @access public
  629. * @see _EachChild()
  630. * @see _EachChildArray()
  631. */
  632. function _ChildLoop($reset,$ReturnObj)
  633. {
  634. if(!is_array($this->tmpTag))
  635. return(FALSE);
  636. if(count($this->tmpTag)==0)
  637. return(FALSE);
  638. if($reset)
  639. {
  640. $this->TagFirstTime=TRUE;
  641. return(TRUE);
  642. }
  643. if($this->TagFirstTime)
  644. {
  645. reset($this->tmpTag);
  646. // $this->IntTmpTag=current($this->tmpTag);
  647. if(!is_array($this->tmpTag))
  648. return(FALSE);
  649. // reset($this->IntTmpTag);
  650. $this->TagFirstTime=false;
  651. }
  652. else
  653. // if(!next($this->IntTmpTag))
  654. // {
  655. if(!next($this->tmpTag))
  656. return(FALSE);
  657. // else
  658. // {
  659. // $this->IntTmpTag=current($this->tmpTag);
  660. // reset($this->IntTmpTag);
  661. // }
  662. // }
  663. $value=current($this->tmpTag);
  664. $key=$value['nodename'];
  665. if($ReturnObj)
  666. {
  667. if(!is_array($value))
  668. {
  669. print_r($this->tmpTag);
  670. die();
  671. }
  672. $tmpObj=new CXml2Array($value);
  673. return(array($key,$tmpObj));
  674. }
  675. else
  676. return(array($key,$value));
  677. }
  678.  
  679. }
  680. ?>

Documentation generated on Mon, 28 Mar 2005 15:13:08 +0200 by phpDocumentor 1.3.0RC3