dmaxb
dmaxb

Reputation: 93

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

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!

Upvotes: 9

Views: 1895

Answers (1)

Cl&#233;ment Malet
Cl&#233;ment Malet

Reputation: 5090

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"
      }
    }
  }
}

Upvotes: 4

Related Questions