Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting XML into PHP array with JSON is deleting attributes on some elements

Tags:

json

php

xml

I'm currently processing an extensive XML file, to make some of the processing easier I've used the following method as mentioned extensively on stack overflow

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

This has been awesome but going over my code I've noted some instances where attributes on certain elements aren't converting correctly, at this step $json = json_encode($xml);

Here is a stripped down XML example.

<?xml version="1.0"?>
<property>
    <landDetails>
        <area unit="squareMeter"/>
    </landDetails>
    <buildingDetails>
        <area unit="squareMeter">100</area>
    </buildingDetails>
</property>

and here is the output.

Array (
    [landDetails] => Array (
        [area] => Array (
            [@attributes] => Array (
                [unit] => squareMeter
            )
        )
    )
    [buildingDetails] => Array (
        [area] => 100
    )
)

As seen above if the element contains any info on that exact node the associated attributes with that element are not processed. This is causing significant data loss between the conversion.

Does anyone know how to solve this issue?

Thanks in advance!

like image 431
Devon Mather Avatar asked Sep 05 '14 08:09

Devon Mather


1 Answers

The elements are processed, they are just not being displayed in the case where the node has attributes AND values. In that case, only the values are being displayed.

The json / array conversion you do is not taking that into account, and only keep the to-be displayed values. I'm afraid there is no trick to do that, but here is a function I used when I didn't know how to trickily convert SimpleXML elements (And which is handling the attributes and values separately)

function simplexml_to_array ($xml, &$array) {

  // Empty node : <node></node>
  $array[$xml->getName()] = '';

  // Nodes with children
  foreach ($xml->children() as $child) {
    simplexml_to_array($child, $array[$xml->getName()]);
  }

  // Node attributes
  foreach ($xml->attributes() as $key => $att) {
      $array[$xml->getName()]['@attributes'][$key] = (string) $att;
  }

  // Node with value
  if (trim((string) $xml) != '') {
    $array[$xml->getName()][] = (string) $xml; 
  }

}

$xml = simplexml_load_string($xml);
simplexml_to_array($xml, $arr);
var_dump($arr);

Output :

array(1) {
  ["property"]=>
  array(2) {
    ["landDetails"]=>
    array(1) {
      ["area"]=>
      array(1) {
        ["@attributes"]=>
        array(1) {
          ["unit"]=>
          string(11) "squareMeter"
        }
      }
    }
    ["buildingDetails"]=>
    array(1) {
      ["area"]=>
      array(2) {
        ["@attributes"]=>
        array(1) {
          ["unit"]=>
          string(11) "squareMeter"
        }
        [0]=>
        string(3) "100"
      }
    }
  }
}
like image 76
Clément Malet Avatar answered Nov 12 '22 21:11

Clément Malet