- <?php
- /*
- * CXml2Array.php
- * $Header: d:\cvs/classistd/sptpl/CXml2Array.php,v 2.9 2005/03/17 12:47:01 Darvin Exp $
- *
- * Class to convert an XML file into array
- *
- * Copyright (C) 2003-2005 Andrioli Darvin <darvin at andrioli.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- class CXml2Array
- {
- /**
- * Array containg the file XML
- * structure:
- * ['text'] -> text inside the tag
- * ['attrib'][attribname] -> tag's attribute
- * ['child'][] -> child tag information. It holds many child with the
- * same name
- *
- * @var array
- */
- var $TheArray;
-
- /**
- * Temporary arrays
- */
- var $tmpAttrib;
- var $tmpTag;
-
- var $AttribFirstTime;
- var $TagFirstTime;
- var $IntTmpTag;
- /**
- * Which PHP extension the module uses to parse the XML data
- * @var string
- * @see _WhichExtension()
- */
- var $Extension;
- /**
- * Class initializer
- * @param mixed object DOM XML or array returned by GetTag
- * @access public
- * @see GetTag()
- */
- function CXml2Array($node='')
- {
- $this->Extension=$this->_WhichExtension();
- if(!is_string($node))
- {
- //
- if(is_array($node))
- $this->LoadFromArray($node);
- else
- {
- if(is_object($node))
- $this->TheArray=$this->Parse($node);
- else
- trigger_error('Invalid parameter',E_USER_ERROR);
- }
- $this->tmpAttrib=$this->TheArray['attrib'];
- $this->tmpTag=$this->TheArray['child'];
- $this->AttribFirstTime=true;
- $this->TagFirstTime=true;
- }
- }
-
- /**
- * Load data from filename
- * @param string filename
- * @return bool true if the file is successfully parsed
- * @access public
- */
- function LoadFromFile($FileName)
- {
- if($this->Extension=='DOM')
- {
- $doc = new DOMDocument; // require zend.ze1_compatibility_mode = off
- if(!$doc->load(realpath($FileName)))
- trigger_error('Error parsing the file '.$FileName,E_USER_ERROR);
- $root=$doc->documentElement;
- }
- else
- {
- if(!$this->TplDom = domxml_open_file(realpath($FileName)))
- trigger_error('Error parsing the file '.$FileName,E_USER_ERROR);
- $root = $this->TplDom->document_element();
- }
- $this->TheArray=$this->Parse($root);
- $this->tmpAttrib=$this->TheArray['attrib'];
- $this->tmpTag=$this->TheArray['child'];
- $this->AttribFirstTime=true;
- $this->TagFirstTime=true;
- }
-
- /**
- * Load data from xml string
- * @param string XML text
- * @return bool true if the file is successfully parsed
- * @access public
- */
- function LoadFromString($XmlStr)
- {
- if($this->Extension=='DOM')
- {
- $dom = new DOMDocument();
- $dom->loadXML($XmlStr);
- $root = $dom->documentElement;
- }
- else
- {
- if(!$dom = domxml_open_mem($XmlStr))
- trigger_error("Internal Error while creating standard font",E_USER_ERROR);
- $root = $dom->document_element();
- }
- $this->TheArray=$this->Parse($root);
- $this->tmpAttrib=$this->TheArray['attrib'];
- $this->tmpTag=$this->TheArray['child'];
- $this->AttribFirstTime=true;
- $this->TagFirstTime=true;
- }
-
- /**
- * Evaluate which PHP extension the module should use to parse the XML data
- * PHP4 -> DOMXML
- * PHP5 -> DOM
- * @access private
- * @return string The extension name
- */
- function _WhichExtension()
- {
- return(($this->__php5())?'DOM':'DOMXML');
- }
-
- /**
- * Return True if the current PHP version is 5
- * False if is PHP4
- * @return boolean
- * @access public
- */
- function __php5()
- {
- return((version_compare(phpversion(), "5.0.0", "<")==-1)?false:true);
- }
-
- /**
- * Parse one XML node. With PHP4 it uses DOMXML extension, with PHP it
- * uses DOM extension.
- * @param object DOMXML/DOM
- * @param integer Nesting level
- * @access private
- */
- function Parse($Node,$level=0,$NodeName='')
- {
- if($this->Extension=='DOM')
- $ret=$this->ParseDOM($Node,$level,$NodeName);
- else
- $ret=$this->ParseDOMXML($Node,$level,$NodeName);
- return($ret);
- }
-
- /**
- * Parse one XML node.
- * @param object DOMXML
- * @param integer Nesting level
- * @access private
- */
- function ParseDOMXML($Node,$level=0,$NodeName='')
- {
- $type=array( 1 =>'XML_ELEMENT_NODE',
- 2 =>'XML_ATTRIBUTE_NODE',
- 3 =>'XML_TEXT_NODE',
- 4 =>'XML_CDATA_SECTION_NODE',
- 5 =>'XML_ENTITY_REF_NODE',
- 6 =>'XML_ENTITY_NODE',
- 17 =>'XML_ENTITY_DECL_NODE'
- );
- // print_r($Node);
- $Text='';
- //$NodeName='';
- $Contents=array();
- $Attrib=array();
- // load the attribs
- $AttrTbl=$Node->attributes();
- if($AttrTbl) {
- // First I'm looking for the attrib Id
- foreach($AttrTbl as $Att)
- {
- $AttribName=strtolower($Att->name());
- $Attrib[$AttribName]=$Att->value();
- }
- }
- // childs parse
- $child = $Node->first_child();
- while($child) {
- //echo '<br>child:';
- // echo '<br>['.$level.']'.$type[$child->node_type()];
- switch($child->node_type())
- {
- case XML_ENTITY_REF_NODE :
- $ret=$this->Parse($child,$level+1);
- // var_dump($ret);
- foreach($ret['child'] as $key => $value)
- {
- $Contents[]=$value;
- }
- //return($ret);
- break;
- case XML_ENTITY_DECL_NODE :
- $ret=$this->Parse($child,$level+1);
- return($ret);
- break;
- case XML_TEXT_NODE:
- $Text.=rtrim($child->node_value());
- break;
- case XML_CDATA_SECTION_NODE:
- $Text.=rtrim($child->node_value());
- break;
- case XML_ELEMENT_NODE:
- $NName=strtolower($child->node_name());
- $Contents[]=$this->Parse($child,$level+1,$NName);
- break;
- } // switch node type
- $child = $child->next_sibling();
- }
- return(array('child' => $Contents,
- 'text' => $Text,
- 'attrib' => $Attrib,
- 'nodename' => $NodeName)
- );
- }
-
- /**
- * Parse one XML node.DOM version (PHP5)
- * @param object DOM
- * @param integer Nesting level
- * @access private
- */
- function ParseDOM($Node,$level=0,$NodeName='')
- {
- $type=array( 1 =>'XML_ELEMENT_NODE',
- 2 =>'XML_ATTRIBUTE_NODE',
- 3 =>'XML_TEXT_NODE',
- 4 =>'XML_CDATA_SECTION_NODE',
- 5 =>'XML_ENTITY_REF_NODE',
- 6 =>'XML_ENTITY_NODE',
- 17 =>'XML_ENTITY_DECL_NODE'
- );
- // print_r($Node);
- $Text='';
- //$NodeName='';
- $Contents=array();
- $Attrib=array();
- // load the attribs
- $AttrTbl=$Node->attributes;
- if($AttrTbl) {
- // First I'm looking for the attrib Id
- foreach($AttrTbl as $Att)
- {
- $AttribName=strtolower($Att->name);
- $Attrib[$AttribName]=$Att->value;
- }
- }
- // childs parse
- $child = $Node->firstChild;
- while($child) {
- //echo '<br>child:';
- // echo '<br>['.$level.']'.$type[$child->node_type()];
- switch($child->nodeType)
- {
- case XML_ENTITY_REF_NODE :
- $ret=$this->Parse($child,$level+1);
- // var_dump($ret);
- foreach($ret['child'] as $key => $value)
- {
- //if(array_key_exists($key,$Contents))
- // {
- // $t=array_merge($Contents[$key],$value);
- // $Contents[$key]=$t;
- // }
- // else
- // {
- $Contents[]=$value;
- // }
- }
- //return($ret);
- break;
- case XML_ENTITY_DECL_NODE :
- $ret=$this->Parse($child,$level+1);
- return($ret);
- break;
- case XML_TEXT_NODE:
- $Text.=rtrim($child->nodeValue);
- break;
- case XML_CDATA_SECTION_NODE:
- $Text.=rtrim($child->nodeValue);
- //$Text.=ereg_replace(' ',' ',$passo1);
- //$Text.=htmlentities(trim($child->node_value()));
- break;
- case XML_ELEMENT_NODE:
- $NName=strtolower($child->nodeName);
- $Contents[]=$this->Parse($child,$level+1,$NName);
- break;
- } // switch node type
- $child = $child->nextSibling;
- }
- return(array('child' => $Contents,
- 'text' => $Text,
- 'attrib' => $Attrib,
- 'nodename' => $NodeName)
- );
- }
-
- /**
- * Load the array from another array retrieved from this class.
- * It is usefull to apply the module's function to the deepest part of the
- * original array
- * @param array
- */
- function LoadFromArray($data)
- {
- $this->TheArray=$data;
- // if(!array_key_exists('attrib',$this->TheArray))
- // $this->TheArray['attrib']=array();
- if(!array_key_exists('text',$this->TheArray))
- $this->TheArray['text']='';
- }
-
- /**
- * Dump the array contents in human format.
- * Usefull for debug purpose
- * @access public
- */
- function ArrayDump()
- {
- // var_dump($this->TheArray);
- //echo '<hr>';
- $this->_dump($this->TheArray);
- }
-
- /**
- * Internal function used to dump the array
- * @param array data to dump
- * @param integer
- * @access private
- */
- function _dump($data,$level=0)
- {
- $ta=20;
- $c='.';
- echo str_repeat($c,$level*$ta).'[text]:'.$data['text'].'<br>';
- echo str_repeat($c,$level*$ta).'[nodename]:'.$data['nodename'].'<br>';
- echo str_repeat($c,$level*$ta).'[attrib]:'.'<br>';
- foreach($data['attrib'] as $key => $value)
- {
- echo str_repeat($c,$level*$ta).'.........['.$key.']:'.$value.'<br>';
- }
- echo str_repeat($c,$level*$ta).'[child]:'.'<br>';
- foreach($data['child'] as $key => $value)
- {
- //var_dump($data['tag']);
- echo str_repeat($c,$level*$ta).'.........['.$key.']:'.'<br>';
- // foreach($data['child'][$key] as $key1 => $value1)
- // {
- //var_dump($value1);
- // echo str_repeat($c,($level+1)*$ta-4).'['.$key1.']';
- $this->_dump($value,$level+1);
- // }
- }
- }
-
-
- /**********************************
- * Retrieve functions
- ************************************/
-
- /**
- * Does exist the request tag? The function looks only if the tag exists
- * as child of the root element.
- * @param string
- * @return bool
- * @access public
- */
- function ExistTag($TagName)
- {
- $noItem=count($this->TheArray['child']);
- $Found=FALSE;
- for($i=0;$i<$noItem&&!$Found;$i++)
- {
- if($this->TheArray['child'][$i]['nodename']==$TagName)
- $Found=TRUE;
- }
- return($Found);
- }
-
- /**
- * Does exist the request attribute? The function looks only if the attribute exists
- * as child of the root element.
- * @param string
- * @return bool
- * @access public
- */
- function ExistAttribute($AttribName)
- {
- return(array_key_exists($AttribName,$this->TheArray['attrib']));
- }
-
- /**
- * Return the XML as array
- * @access public
- */
- function GetArray()
- {
- return($this->TheArray);
- }
-
- /**
- * The function return all childs of the root element named $TagName
- * @param string
- * @return array
- * @access public
- */
- function GetTag($TagName)
- {
- $noItem=count($this->TheArray['child']);
- $ret=array();
- $Found=FALSE;
- for($i=0;$i<$noItem;$i++)
- {
- if($this->TheArray['child'][$i]['nodename']==$TagName)
- {
- $ret[]=$this->TheArray['child'][$i];
- $Found=TRUE;
- }
- }
-
- if($Found)
- return($ret);
- else
- return(FALSE);
- }
-
- /**
- * The function return all childs of the root element named $TagName
- * @param string
- * @return array
- * @access public
- */
- function GetTagPos($TagName,$Position=0)
- {
- $count=0;
- $noItem=count($this->TheArray['child']);
- for($i=0;$i<$noItem;$i++)
- {
- if($this->TheArray['child'][$i]['nodename']==$TagName)
- {
- if($count==$Position)
- return($this->TheArray['child'][$i]);
- $count++;
- }
- }
- return(FALSE);
- }
-
- /**
- * The function return all childs of $TagName. Note $TagName should be a child of the
- * root element
- * @param string
- * @param integer Select from which child retrieve the information, if more child of
- * root element have the same name
- * @return array
- * @access public
- */
- function GetTagChilds($TagName,$Position=0)
- {
- $noItem=count($this->TheArray['child']);
- $count=0;
- for($i=0;$i<$noItem;$i++)
- {
- if($this->TheArray['child'][$i]['nodename']==$TagName)
- {
- if($count==$Position)
- return($this->TheArray['child'][$i]['child']);
- $count++;
- }
- }
- return(FALSE);
- }
-
- /**
- * The function return all attributes of $TagName. Note $TagName should be a child of the
- * root element
- * @param string
- * @param integer Select from which child retrieve the information, if more child of
- * root element have the same name
- * @return array
- * @access public
- */
- function GetTagAttributes($TagName,$Position=0)
- {
- $noItem=count($this->TheArray['child']);
- $count=0;
- for($i=0;$i<$noItem;$i++)
- {
- if($this->TheArray['child'][$i]['nodename']==$TagName)
- {
- if($count==$Position)
- return($this->TheArray['child'][$i]['attrib']);
- $count++;
- }
- }
- return(FALSE);
- }
-
- /**
- * Return value of the named attribute
- * @param string
- * @return string
- * @access public
- */
- function GetAttribute($AttribName)
- {
- if($this->ExistAttribute($AttribName))
- return($this->TheArray['attrib'][$AttribName]);
- else
- return(FALSE);
- }
-
- /**
- * Return value of the root tag
- * @return string
- * @access public
- */
- function GetText()
- {
- return($this->TheArray['text']);
- }
-
- /**
- * Return the name of the root tag
- * @return string
- * @access public
- */
- function GetNodeName()
- {
- return($this->TheArray['nodename']);
- }
-
-
- /**
- * The function iterate over attribute's array of the root element
- * @param bool Set to TRUE to reset the internal pointer
- * @return array
- * @access public
- */
- function EachAttribute($reset=FALSE)
- {
- // var_dump($this->TheArray);
- // var_dump($this->tmpAttrib);
- if(!is_array($this->tmpAttrib))
- return(FALSE);
- if($reset)
- {
- $this->AttribFirstTime=TRUE;
- return(TRUE);
- }
-
- if($this->AttribFirstTime)
- {
- reset($this->tmpAttrib);
- $this->AttribFirstTime=false;
- }
- else
- if(!next($this->tmpAttrib))
- return(FALSE);
- $value=current($this->tmpAttrib);
- $key=key($this->tmpAttrib);
-
- return(array($key,$value));
- }
-
- /**
- * The function iterate over tag's array of the root element
- * Public method
- * @param bool Set to TRUE to reset the internal pointer
- * @return object CXml2Array
- * @access public
- * @see _ChildLoop()
- */
- function EachChild($reset=FALSE)
- {
- return($this->_ChildLoop($reset,TRUE));
- }
-
- /**
- * The function iterate over tag's array of the root element
- * Public method
- * @param bool Set to TRUE to reset the internal pointer
- * @return array
- * @access public
- * @see _ChildLoop()
- */
- function EachChildArray($reset=FALSE)
- {
- return($this->_ChildLoop($reset,FALSE));
- }
-
- /**
- * The function iterate over tag's array of the root element
- * @param bool Set to TRUE to reset the internal pointer (return TRUE)
- * @param bool Set to TRUE to return an object CXml2Array, o FALSE to return tha
- * child's value as array
- * @return object CXml2Array
- * @access public
- * @see _EachChild()
- * @see _EachChildArray()
- */
- function _ChildLoop($reset,$ReturnObj)
- {
- if(!is_array($this->tmpTag))
- return(FALSE);
- if(count($this->tmpTag)==0)
- return(FALSE);
- if($reset)
- {
- $this->TagFirstTime=TRUE;
- return(TRUE);
- }
- if($this->TagFirstTime)
- {
- reset($this->tmpTag);
- // $this->IntTmpTag=current($this->tmpTag);
- if(!is_array($this->tmpTag))
- return(FALSE);
- // reset($this->IntTmpTag);
- $this->TagFirstTime=false;
- }
- else
- // if(!next($this->IntTmpTag))
- // {
- if(!next($this->tmpTag))
- return(FALSE);
- // else
- // {
- // $this->IntTmpTag=current($this->tmpTag);
- // reset($this->IntTmpTag);
- // }
- // }
-
- $value=current($this->tmpTag);
- $key=$value['nodename'];
- if($ReturnObj)
- {
- if(!is_array($value))
- {
- print_r($this->tmpTag);
- die();
- }
- $tmpObj=new CXml2Array($value);
- return(array($key,$tmpObj));
- }
- else
- return(array($key,$value));
- }
-
- }
- ?>