PHP Classes

File: CXml2Array.php

Recommend this page to a friend!
  Classes of Andrioli Darvin   SpoolTemplate   CXml2Array.php   Download  
File: CXml2Array.php
Role: Auxiliary script
Content type: text/plain
Description: Class Xml2Array source
Class: SpoolTemplate
Database report generation based on templates
Author: By
Last change: Added support to DOM extension in PHP5 environment
Date: 19 years ago
Size: 16,770 bytes
 

Contents

Class file image Download
<?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(' ','&nbsp;',$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)); } } ?>