1

I'm trying to convert XML which has namespaces, attributes to array by using JsonSerializable& iterator_to_array() as suggested by @hakre here: https://hakre.wordpress.com/2013/07/10/simplexml-and-json-encode-in-php-part-iii-and-end/

The issue I'm facing is when a node in the XML has just one child. Here's a description of the problem:

<node1 attr1="val1" attr2="val2>
    <node2 attr3="val3" attr4="val4" />
    <node2 attr3="val3" attr4="val4" />
    <node2 attr3="val3" attr4="val4" />
</node1>

So the array would be

[node1] => Array
                    (
                        [@attributes] => Array
                            (
                                [attr1] => val1
                                [attr2] => val2
                            )
                        [node2] => Array
                            (
                                [0] => Array
                                    (
                                        [@attributes] => Array
                                               (
                                                   [attr3] => val3
                                                   [attr4] => val4
                                               )
                                    )

                                [1] => Array
                                    (
                                        [@attributes] => Array
                                               (
                                                   [attr3] => val3
                                                   [attr4] => val4
                                               )
                                    )

                                [2] => Array
                                    (
                                        [@attributes] => Array
                                               (
                                                   [attr3] => val3
                                                   [attr4] => val4
                                               )
                                    )
                            )
                    )

So I'd use something like:

foreach($array['node1']['node1'] AS $node){
    print_r($node['@attributes']);
}

But some times...

<node1 attr1="val1" attr2="val2>
    <node2 attr3="val3" attr4="val4" />
</node1>

Then array be like:

[node1] => Array
                    (
                        [@attributes] => Array
                            (
                                [attr1] => val1
                                [attr2] => val2
                            )
                        [node2] => Array
                            (
                                  [@attributes] => Array
                                        (
                                             [attr3] => val3
                                             [attr4] => val4
                                        )
                            )
                    )

In that case the foreach would fail because @attributes is direct child of node2 unlike the first case node2[0]['@attributes'].

The XML is a webservice response and the whole information is in attributes. A particular node might have just one child or more with no anticipation.

How do I make sure that I have a 0th child node even if there is just one child like below?

Required O/P:

[node1] => Array
                    (
                        [@attributes] => Array
                            (
                                [attr1] => val1
                                [attr2] => val2
                            )
                        [node2] => Array
                            (
                                  [0] => Array
                                    (
                                        [@attributes] => Array
                                               (
                                                   [attr3] => val3
                                                   [attr4] => val4
                                               )
                                    )
                            )
                    )

Note: A simple workaround I devised

if(isset($array['node1']['node2']['@attributes']){
    print_r($array['node1']['node2']['@attributes']);
}
else{
    foreach($array['node1']['node1'] AS $node){
        print_r($node['@attributes']);
    }
}

But the XML response is easily 7000 lines and more that 20 different nodes present in different levels. I dont want to use this condition explicitly for each node.

PS: I have looked into this question but I want the opposite. Add a 0th item even if there is one child PHP convert XML to JSON group when there is one child

Community
  • 1
  • 1
enemetch
  • 492
  • 2
  • 8
  • 21

1 Answers1

1

I'm working currently on the implementation of jsonSerialize that always produces arrays, even if the XML source contains only one child. https://github.com/vitr/SimpleXMLExtended
I fed your XML example and it produced (perhaps accidentally) the required o/p, have a look
https://eval.in/385372
I may include your case in my test suite, if it really solves the issue. If not, you may clone the repo and make further adjustments. Anyway, maybe it points you to the right direction.

vitr
  • 6,766
  • 8
  • 30
  • 50
  • It worked for the XML in question, but I replace it with actual XML and I got back and empty array. :/ What more info would you need? – enemetch Jun 22 '15 at 10:29
  • BTW the XML response we're looking at is [TravelPort uAPI for Flights](https://support.travelport.com/webhelp/uapi/uAPI.htm#Air/Low_Fare_Shopping/Low_Fare_Shopping_(Synchronous).htm%3FTocPath%3DAir%2520Shopping%2520and%2520Booking%7CLow%2520Fare%2520Shopping%7C_____1) – enemetch Jun 22 '15 at 10:45
  • @eNeMetcH I'm sorry, but this is SOAP not plain XML I'm dealing with, try something like this http://stackoverflow.com/questions/21777075/how-to-convert-soap-response-to-php-array – vitr Jun 22 '15 at 11:23
  • Is it plain XML if I remove the SOAP envelope & body tags? – enemetch Jun 22 '15 at 11:27
  • let's try, seems simplexml can't deal with soap because of the colon : – vitr Jun 22 '15 at 11:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/81175/discussion-between-enemetch-and-vitr). – enemetch Jun 22 '15 at 12:17