Thanks rein_baarsma33 AT hotmail DOT com for bugfixes.
This is my new child of XML parsing method based on my and yours modification.
XML2ASSOC Is a complete solution for parsing ordinary XML
<?php
/**
* XML2Assoc Class to creating
* PHP Assoc Array from XML File
*
* @author godseth (AT) o2.pl & rein_baarsma33 (AT) hotmail.com (Bugfixes in parseXml Method)
* @uses XMLReader
*
*/
class Xml2Assoc {
/**
* Optimization Enabled / Disabled
*
* @var bool
*/
protected $bOptimize = false;
/**
* Method for loading XML Data from String
*
* @param string $sXml
* @param bool $bOptimize
*/
public function parseString( $sXml , $bOptimize = false) {
$oXml = new XMLReader();
$this -> bOptimize = (bool) $bOptimize;
try {
// Set String Containing XML data
$oXml->XML($sXml);
// Parse Xml and return result
return $this->parseXml($oXml);
} catch (Exception $e) {
echo $e->getMessage();
}
}
/**
* Method for loading Xml Data from file
*
* @param string $sXmlFilePath
* @param bool $bOptimize
*/
public function parseFile( $sXmlFilePath , $bOptimize = false ) {
$oXml = new XMLReader();
$this -> bOptimize = (bool) $bOptimize;
try {
// Open XML file
$oXml->open($sXmlFilePath);
// // Parse Xml and return result
return $this->parseXml($oXml);
} catch (Exception $e) {
echo $e->getMessage(). ' | Try open file: '.$sXmlFilePath;
}
}
/**
* XML Parser
*
* @param XMLReader $oXml
* @return array
*/
protected function parseXml( XMLReader $oXml ) {
$aAssocXML = null;
$iDc = -1;
while($oXml->read()){
switch ($oXml->nodeType) {
case XMLReader::END_ELEMENT:
if ($this->bOptimize) {
$this->optXml($aAssocXML);
}
return $aAssocXML;
case XMLReader::ELEMENT:
if(!isset($aAssocXML[$oXml->name])) {
if($oXml->hasAttributes) {
$aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
} else {
if($oXml->isEmptyElement) {
$aAssocXML[$oXml->name] = '';
} else {
$aAssocXML[$oXml->name] = $this->parseXML($oXml);
}
}
} elseif (is_array($aAssocXML[$oXml->name])) {
if (!isset($aAssocXML[$oXml->name][0]))
{
$temp = $aAssocXML[$oXml->name];
foreach ($temp as $sKey=>$sValue)
unset($aAssocXML[$oXml->name][$sKey]);
$aAssocXML[$oXml->name][] = $temp;
}
if($oXml->hasAttributes) {
$aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
} else {
if($oXml->isEmptyElement) {
$aAssocXML[$oXml->name][] = '';
} else {
$aAssocXML[$oXml->name][] = $this->parseXML($oXml);
}
}
} else {
$mOldVar = $aAssocXML[$oXml->name];
$aAssocXML[$oXml->name] = array($mOldVar);
if($oXml->hasAttributes) {
$aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
} else {
if($oXml->isEmptyElement) {
$aAssocXML[$oXml->name][] = '';
} else {
$aAssocXML[$oXml->name][] = $this->parseXML($oXml);
}
}
}
if($oXml->hasAttributes) {
$mElement =& $aAssocXML[$oXml->name][count($aAssocXML[$oXml->name]) - 1];
while($oXml->moveToNextAttribute()) {
$mElement[$oXml->name] = $oXml->value;
}
}
break;
case XMLReader::TEXT:
case XMLReader::CDATA:
$aAssocXML[++$iDc] = $oXml->value;
}
}
return $aAssocXML;
}
/**
* Method to optimize assoc tree.
* ( Deleting 0 index when element
* have one attribute / value )
*
* @param array $mData
*/
public function optXml(&$mData) {
if (is_array($mData)) {
if (isset($mData[0]) && count($mData) == 1 ) {
$mData = $mData[0];
if (is_array($mData)) {
foreach ($mData as &$aSub) {
$this->optXml($aSub);
}
}
} else {
foreach ($mData as &$aSub) {
$this->optXml($aSub);
}
}
}
}
}
?>
[EDIT BY danbrown AT php DOT net: Fixes were also provided by "Alex" and (qdog AT qview DOT org) in user notes on this page (since removed).]