fluidxml icon indicating copy to clipboard operation
fluidxml copied to clipboard

Export XML to array() or stdClass objects

Open kinekt4 opened this issue 7 years ago • 7 comments

It would be nice to be able to export to arrays or stdClass Objects

eg.

$xml = <<<XML
<animal operation="create">
    <type>Herbivore</type>
    <attribute>
      <legs>4</legs>
      <head>1</head>
    </attribute>
</animal>
XML;

// IMPORT
$doc = new FluidXml($xml);
// EXPORT
$arr = $doc->exportArray();
// ARRAY
var_export($arr);

Array (
    'animal' => Array (
      '@operation' => 'create',
      'type' => 'Herbivore',
      'attribute' => Array(
        'legs' => 4,
        'head' => 1
      )
  )
)

Would like to hear if this could be implemented.

Thanks

kinekt4 avatar Feb 15 '17 22:02 kinekt4

Or perhaps I should use PEAR::XML_Serializer ?

kinekt4 avatar Feb 15 '17 23:02 kinekt4

How would namespaces be treated in the expected output?

E.g.

<animal operation="create">
    <type>Herbivore</type>
    <attribute xmlns:foo="http://namespace.foo">
      <foo:legs>4</foo:legs>
      <foo:head>1</foo:head>
    </attribute>
</animal>

alepeino avatar Mar 02 '17 14:03 alepeino

To convert a XML into a ARRAY is easy

$sxml = simplexml_load_string($xmlcontent);
$array = json_decode(json_encode($sxml), true);

With this we get the array that represents the XML.

But FluidXML does not do the reverse, becose the structure of the attributes does not follow the same rule, in the case of SimpleXML the attributes are created in this way:

'infNFe' => [
            '@attributes' => [
                    'Id' => 'NFe35150258716523000119550000000344891840634422',
                    'versao' => '2.00'
              ],

NOTE: this is easily to correct! In addition SimpleXML saves repeated tags as a subarrays not replicate the tag name, like:

'det' => [ 0 => [ others tag for det node 0],
              1 => [ others tag for det node 1],

In FluidXML this tag 'det' after 0 is ignored and puts all nodes in first 'det', i dont know correct this

All xml with which I read are big and we can say a little complex see in sped-nfe

robmachado avatar Apr 23 '17 19:04 robmachado

@alepeino As far as I can tell, there's no special notation for namespaces.

So maybe we can reuse the attribute notation:

Array (
    'animal' => Array (
      '@operation' => 'create',
      'type' => 'Herbivore',
      'attribute' => Array(
        '@xmlns:foo' => 'http://namespace.foo'
        'legs' => 4,
        'head' => 1
      )
  )
)

kinekt4 avatar Jun 08 '17 02:06 kinekt4

@denormalizer Namespaces are special in that xmlns:foo lets you create a sort of prefix alias for the scope of the declaring element and its descendants. So, in my example, both <legs/> and <head/> belong in the http://namespace.foo namespace, but your example does not represent that.

I'm not saying it's not doable, but it may be not as straightforward as one may think.

alepeino avatar Jun 08 '17 19:06 alepeino

Sorry I didn't see your namespaces in the child nodes.

For simplicity, I suggest the following:

Array (
    'animal' => Array (
      '@operation' => 'create',
      'type' => 'Herbivore',
      'attribute' => Array(
        '@xmlns:foo' => 'http://namespace.foo'
        'foo:legs' => 4,
        'foo:head' => 1
      )
  )
)

That means the translator is namespace agnostic. It is up to the user to generate the correct format.

kinekt4 avatar Jun 09 '17 00:06 kinekt4

My Working implementation using XML_Unserialize (http://pear.php.net/package/XML_Serializer/)

Where $xml is the xml string by @alepeino above. And $arr is the array generated by myself above:

// INITIALIZE
$unserializer = new XML_Unserializer();
// SET OPTIONS
$unserializer->setOption('complexType', 'array');
$unserializer->setOption('parseAttributes', true);
$unserializer->setOption('prependAttributes', '@');
// UNSERIALIZE   
$unserializer->unserialize($xml);
// ARRAY DATA
$arr = $unserializer->getUnserializedData();

kinekt4 avatar Jun 09 '17 00:06 kinekt4