Login   Register  
PHP Classes
elePHPant
Icontem

File: CXml2Array.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  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: 2005-03-22 12:51
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));
}

}
?>