Zend_Config_Xml strange behaviour

Question!

I have a strange problem with Zend_Config_Xml.

Here is an example.

With this xml file https://gist.github.com/883465

this code:

$config = new Zend_Config_Xml('config.xml'); 
var_dump($config->get('elements')->get('element')->toArray()); 

gives:

array(2) { 
  [0]=> 
  array(2) { 
    ["a"]=> 
    array(1) { 
      ["attr"]=> 
      string(2) "at" 
    } 
    ["e"]=> 
    array(3) { 
      [0]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
      [1]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
      [2]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
    } 
  } 
  [1]=> 
  array(2) { 
    ["a"]=> 
    array(1) { 
      ["attr"]=> 
      string(2) "at" 
    } 
    ["e"]=> 
    array(3) { 
      [0]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
      [1]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
      [2]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
    } 
  } 
} 

with this xml file https://gist.github.com/883469

it gives:

array(2) { 
  ["a"]=> 
  array(1) { 
    ["attr"]=> 
    string(2) "at" 
  } 
  ["e"]=> 
  array(3) { 
    [0]=> 
    array(1) { 
      ["attr"]=> 
      string(2) "at" 
    } 
    [1]=> 
    array(1) { 
      ["attr"]=> 
      string(2) "at" 
    } 
    [2]=> 
    array(1) { 
      ["attr"]=> 
      string(2) "at" 
    } 
  } 
} 

and I expect:

array(1) { 
  [0]=> 
  array(2) { 
    ["a"]=> 
    array(1) { 
      ["attr"]=> 
      string(2) "at" 
    } 
    ["e"]=> 
    array(3) { 
      [0]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
      [1]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
      [2]=> 
      array(1) { 
        ["attr"]=> 
        string(2) "at" 
      } 
    } 
  } 
} 

This is tricky when you want to iterate over elements

$config = new Zend_Config_Xml('config.xml'); 
foreach($config->get('elements')->get('element') as $element); 

which is fine if there are more then one elements, but if you have only one, you'll end up iterating over element children!

Any idea?

EDIT:

I came up with an ugly workaround:

if (0 !== $config->get('elements')->get('element')) { // }

This helps me to identify if there is more then one elements under elements tag.

Very ugly.

Anithing smarter?

By : umpirsky


Answers

It seems that Zend_Config_Xml explicitly collapses such 1-element collections (there's an if statement in the source that does this). Some possible workarounds:

  • Overload Zend_Config_Xml and fix the loader code so it doesn't collapse 1-element collections
  • Overload Zend_Config_Xml and overload get() to include your ugly workaround in a cleaner way.
  • Use SimpleXML instead of Zend_Config_Xml


This video can help you solving your question :)
By: admin