Search code examples
phpxmlsimplexml

XML to PHP array when simpleXML isn't acurate


Ok so i have a problem where i am pulling data base from an API and the structure is returned as below:

<Response id="responceidgoeshere">
  <block name="addresses">
    <block>
      <a name="building" format="text">#NAME/NUM#</a>
      <a name="sub-premise" format="text">#SUB-PREM#</a>
      <a name="street" format="text">#STREET#</a>
      <a name="locality" format="text">#LOCAL#</a>
      <a name="city" format="text">#CITY#</a>
      <a name="postcode" format="text">#POSTCODE#</a>
      <a name="ref" format="text">#REF#</a>
      <a name="csscode" format="text">#CSS#</a>
    </block>
    <block>
      <a name="building" format="text">#NAME/NUM#</a>
      <a name="street" format="text">#STREET#</a>
      <a name="locality" format="text">#LOCAL#</a>
      <a name="city" format="text">#CITY#</a>
      <a name="postcode" format="text">#POSTCODE#</a>
      <a name="ref" format="text"/>
      <a name="csscode" format="text"/>
    </block>
    </block>
</Response>

However, you can see the data changes slightly between results depending on the address. When i use simpleXML to convert to PHP array i end up with the following:

EDIT: including conversion method:

$xml=simplexml_load_string($result, "SimpleXMLElement", LIBXML_NOCDATA);
$json=json_encode($xml);
$array=json_decode($json,TRUE);

Result:

[0] => Array
    (
        [a] => Array
            (
                [0] => #NAME/NUM#
                [1] => #SUB-PREM#
                [2] => #STREET#
                [3] => #LOCAL#
                [4] => #CITY#
                [5] => #POSTCODE#
                [6] => #REF#
                [7] => #CSS#
            )
    [1] => Array
    (
        [a] => Array
            (
                [0] => #NAME/NUM#
                [1] => #STREET#
                [2] => #LOCAL#
                [3] => #CITY#
                [4] => #POSTCODE#
                [5] => #REF#
                [6] => #CSS#
            )

I ideally need a way to create a PHP array with the "name" attr as the key. Does anyone know the best way to do this as the standard simpleXML is too inconsitent for what i need as there wont always be a sub premice element and sometimes there will be a county element too.

EDIT: Example of desired structure:

[0]=array
(
   [a]=array
   (
       ['building'] => #NAME/NUM#,
       ['sub-premise'] => #SUB-PREM#,
       ['street'] => #STREET#,
       etc...
   )
)

Solution

  • Converting a SimpleXMLElement object to an array using either json_decode/encode or casting with (array) is almost always going to end up losing data (especially XML attributes). You'll find it a lot easier trying to access them using their native API rather than trying to blindly convert them into something else.

    What you need to do can be achieved quite easily by looping over the elements, and building an array indexed by the name attributes:

    $result = [];
    
    foreach ($sxml->block->block as $block) {
        $row = [];
    
        foreach ($block->a as $a) {
            $row[(string) $a['name']] = (string) $a;
        }
    
        $result[] = $row;
    }
    

    See https://3v4l.org/mBoFO