made this class (under beta testing atm) which loads config data from pretty special xmls.. thought zend_config_xml is drunk and stupid
sections can be inherited, you can define attributes and have special attributes to handle the parsing.. some features are not implemented yet..
teh pwnage code:
class Gizmo_Config_Xml {
public $data;
private $protectedAttributes = array( "_extends"=>"string","_private"=>"boolean" );
public function __construct($filename,$section = null){
if (empty($filename)) {
throw new Exception('Filename is not set');
}
$config = simplexml_load_file($filename);
if (null === $section)
foreach ($config as $sectionName => $sectionData){
$this->$sectionName = $sectionData;
}
}
public function __set($var,$val){
foreach ($val->attributes() as $k=>$v)
$this->data[$var]['attributes'][$k]= (string) $v;
$this->data[$var] = $this->_processSection($val,$var);
}
private function _processSection($xmlObj){
$config = array();
if(count($xmlObj->children())>0){
foreach($xmlObj->children() as $k=>$v)
$config['elements'][$k] = $this->_processSection($v);
}
foreach($xmlObj->attributes() as $k=>$v)
$config['attributes'][$k] = (string) $v;
if(count($xmlObj->children())==0)
$config['value'] = (string) $xmlObj;
return $config;
}
private function _toArray($data,$sn){
if(is_array($data['attributes'])){
foreach($data['attributes'] as $k=>$v)
if(array_key_exists($k,$this->protectedAttributes)){
try{
settype($v, $this->protectedAttributes[$k]);
}catch (Exception $e){
echo $e->getMessage();
}
if($k=="_extends") {
$ret_data = $this->_arrayMergeRecursive($this->data[$v],$data);
unset($ret_data['attributes']['_extends']);
}
if($k=="_private"){
$flag_private = true;
}
}else
$ret_data['attributes'][$k] = $v;
}
if(is_array($data['elements']))
foreach($data['elements'] as $k=>$v)
$ret_data['elements'][$k] = $this->_toArray($v,$k);
elseif(!isset($ret_data))
$ret_data = $data;
if(count($ret_data['elements']))
unset($ret_data['value']);
else
$ret_data['value'] = $data['value'];
return ($flag_private)?FALSE:$ret_data;
}
private function _arrayMergeRecursive($array1, $array2){
if (is_array($array1) && is_array($array2))
foreach ($array2 as $key => $value)
if (isset($array1[$key]))
$array1[$key] = $this->_arrayMergeRecursive($array1[$key], $value);
else
$array1[$key] = $value;
else
$array1 = $array2;
return $array1;
}
public function toArray(){
$ret = array();
foreach($this->data as $k=>$v){
$a = $this->_toArray($v,$k);
$a!==false ? $ret[$k] = $a : null;
}
return $ret;
}
}
teh xml example:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<_topo _private="true" type="X1:topo">
<catId type="long" optional="true"></catId>
<topoId type="long" optional="true" />
<netId type="long">0</netId>
</_topo>
<_pagi _private="true" type="X2:Pagi" namespace="http://x.com/ws/schema">
<cnt type="boolean" />
<pageNum type="positiveinteger">1</pageNum>
<ipp type="positiveInteger">10</ipp>
</_pagi>
<_sort _private="true" type="X3:Sort" namespace="http://x.com/ws/schema">
<sortBy type="string" enum="viewCount,price,averageRating">enum[0]</sortBy>
<sortOrder type="string" enum="asc,desc">enum[0]</sortOrder>
</_sort>
<getSomeList>
<xId type="long" optional="true" />
<topology _extends="_topo" />
<pagination _extends="_pagi" />
<sort _extends="_sort" />
<testParam _extends="_sort">
<testSubParam type="Qx:test" namespace="y.com">
<testSubSubParam type="long" />
</testSubParam>
</testParam>
</getSomeList>
</config>
tip: it can be used in some nifty soap actions