0

I am using PHP and working with the following XML response:

<CompressedInventoryResults xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/rpc/Gateway">
<CompressedVehicles>
<F _0="vin" _1="stock" _2="msrp" _3="type" _4="year" _5="make" _6="model" _7="imagelist" _8="stockimage"> 
<RS> 
    <R_ID="9002250">
        <VS>
            <V _0="WA1CMAFP3FA096506" _1="A096506" _2="54305" _3="New" _4="2015" _5="Audi" _6="Q5" _7="http://content.homenetiol.com/640x480/53ef04aa3c46463aaa4fd91b13c00037.jpg|http://content.homenetiol.com/640x480/641d6d0da75d457f9026ba35395afdb2.jpg|http://content.homenetiol.com/640x480/4c42f6ff7c7f44eca4613376afef4b22.jpg|http://content.homenetiol.com/640x480/80327447f3bf4421933ca3cae73f9906.jpg|http://content.homenetiol.com/640x480/df7668c77efc4f9692d7809fcb563c98.jpg|http://content.homenetiol.com/640x480/e253195196374c0884c02660fa860b36.jpg|http://content.homenetiol.com/640x480/cae0afb966cf4f1c8430b8807ef761a2.jpg|http://content.homenetiol.com/640x480/b951eee5230c49a583eb0896bb457795.jpg|http://content.homenetiol.com/640x480/a1521a91be614dc19491549fd97fd482.jpg|http://content.homenetiol.com/640x480/563c00e4b19e45f7aba18277541da4c1.jpg|http://content.homenetiol.com/640x480/f47f11edfbf64d5499b842c8b5076376.jpg|http://content.homenetiol.com/640x480/481eb6fcc7b340628b03978e10c2be17.jpg|http://content.homenetiol.com/640x480/dbf461a4a4f349dbbbf9b5bb0b6a0f36.jpg|http://content.homenetiol.com/640x480/3fafb088370f4ee7bec0a3585ef9cec4.jpg|http://content.homenetiol.com/640x480/10908f2cc9da4d418fa752278f635466.jpg|http://content.homenetiol.com/640x480/bf4c4e649b5b4a9db5eb9113ba2d1918.jpg|http://content.homenetiol.com/640x480/7764048b3b5b478a8cf04fb94edad7a8.jpg|http://content.homenetiol.com/640x480/3685da7d1f224386913033e31ee1ebc1.jpg|http://content.homenetiol.com/640x480/f944ff273af044cd91934aabd7651890.jpg|http://content.homenetiol.com/640x480/d8aed10b7d2f471488a1b3f3f6c084d7.jpg|http://content.homenetiol.com/640x480/00d730f575db4db3958a557747358437.jpg|http://content.homenetiol.com/640x480/f104389450e0403f83eb1fb0ffabe3b3.jpg|http://content.homenetiol.com/640x480/df7a41966f0e42859b63738ecaed163e.jpg|http://content.homenetiol.com/640x480/f7d4638bd43d4a119e54decdd0c1d87d.jpg|http://content.homenetiol.com/640x480/29ea28a68bd9426fb85cfc78fb95bdf3.jpg" _8="" />
            <V _0="WAU3GAFD2FN030313" _1="A030313" _2="92095" _3="New" _4="2015" _5="Audi" _6="A8 L" _7="http://content.homenetiol.com/640x480/b358a6a4b58044689c272f098a82e9e9.jpg|http://content.homenetiol.com/640x480/96ac0951ee5043d998d6028ea173ddb8.jpg|http://content.homenetiol.com/640x480/b6a57c34c3bc40acadb09dd6538d6c55.jpg|http://content.homenetiol.com/640x480/17fcb06ee98b41f39a7d9b147652887f.jpg|http://content.homenetiol.com/640x480/3714a45c044a4ddca5a3b7a98b91cd34.jpg|http://content.homenetiol.com/640x480/a5dbc31621574055bbfb7533f4238c14.jpg|http://content.homenetiol.com/640x480/84a9c569786d44b38a65014c20a82160.jpg|http://content.homenetiol.com/640x480/8796e699b9e0451684e0d53d129148b1.jpg|http://content.homenetiol.com/640x480/7c4e8882b392420ca7dfb0f9e9507ede.jpg|http://content.homenetiol.com/640x480/f0d31c64de7549aab70f54fac7bd1056.jpg|http://content.homenetiol.com/640x480/0b4ba4aed8ff41b28c99cb59cc6a6258.jpg|http://content.homenetiol.com/640x480/185f86b4054e4eb08c80eb153527f81a.jpg|http://content.homenetiol.com/640x480/44d65bb194eb4272af48753c8a60622f.jpg|http://content.homenetiol.com/640x480/5d9ac515c8dc4921bc59a1fd1183e95c.jpg|http://content.homenetiol.com/640x480/85c95ff5be6f4bebb79f00e91ac59bf9.jpg|http://content.homenetiol.com/640x480/6be0af9acbc9426d9f4ac9fee1074230.jpg|http://content.homenetiol.com/640x480/cca6e17551f9432fae6859460291d2b2.jpg|http://content.homenetiol.com/640x480/d659f6fccdbb4da0a8bb7f59e493720f.jpg|http://content.homenetiol.com/640x480/7a16f44689d54010b35fa18ce6f1f6cf.jpg|http://content.homenetiol.com/640x480/fdb808588f3045aa9ec85436f5126deb.jpg|http://content.homenetiol.com/640x480/ccf49db7883e47abb14a56a25f050303.jpg|http://content.homenetiol.com/640x480/612d74e48c9e4709ae11645c4dd1ea9b.jpg|http://content.homenetiol.com/640x480/5d398a9e322548cc90bec6ee39307142.jpg|http://content.homenetiol.com/640x480/fc0951a8d8d64e889094f75b8a1f36f2.jpg|http://content.homenetiol.com/640x480/490085ec3cab412ca1aee24c5a169381.jpg|http://content.homenetiol.com/640x480/df9f24289d984879a6cc496c7a9887a6.jpg|http://content.homenetiol.com/640x480/98c616aefd80431687b367dc0805d1e4.jpg" _8="" />
        </VS>
        </R>
</RS>
</F>
</CompressedVehicles>
<ErrorMessage/>
<InventoryResultType>OK</InventoryResultType>
<IsSuccess>true</IsSuccess>
</CompressedInventoryResults>

How can I loop through each of the CompressedVehicles and place each entry with the "V" placeholder into an array with the "F" entry as the header for JSON output?

Or is there better way to interact with this response?

The end goal is to have a more usable output for consumption into other feeds that don't interact well with XML, but do accept JSON.

Thanks in advance.

proph3t
  • 865
  • 2
  • 7
  • 25
  • First of all, it would be nice to know the structure of your desired JSON. Then, above XML is NOT valid XML, and this is a problem. Can you verify if it is exactly the same as your response? – fusion3k Apr 06 '16 at 17:01
  • I guess this is technically a SOAP XML response (according to the documentation). – proph3t Apr 06 '16 at 20:02
  • The desired JSON output would be: `{ vin:"", stock:"", msrp:"", type:"", year:"", make:"", model:"", imagelist:"", stockimage:"" }` – proph3t Apr 06 '16 at 20:10
  • Soap produce valid XML: have you verified that it is exactly as received? Please double-check it: **not valid XML is not parsable:** we can provide you an example but it will don't work. IMO there are at least one to many underscores. – fusion3k Apr 06 '16 at 20:20
  • Yes - I did verify that this is the exact response. – proph3t Apr 06 '16 at 21:01
  • From the documentation -- if it should be of any use. – proph3t Apr 06 '16 at 21:02
  • The returned CompressedVehicles XML string is aimed at reducing the overall payload of the response. The basic structure appears below. ` ` – proph3t Apr 06 '16 at 21:02
  • 1
    `` is not instead `` or `` ? This is according to your comment but not with your question. If you copy and paste, can be an easy way. – fusion3k Apr 06 '16 at 21:07
  • You are correct -- my copy/paste was not the exact response -- it reads `` – proph3t Apr 06 '16 at 21:25
  • There's another problem: `xmlns` is an invalid link and resolves to … `bing.com` – no joke. – kaiser Apr 06 '16 at 21:26
  • This is because it is currently a development ASP.Net XML web service -- once published, the namespace will change to a unique namespace. – proph3t Apr 06 '16 at 21:31

1 Answers1

1

To work with a XML file you have to use a XML Parser. In this answer, you'll see how to use SimpleXML Parser. To encode data in JSON format, you can use json_encode function.

First of all, you have to know the specific structure of your own XML file/string. Under <CompressedInventoryResults> you have this structure:

<CompressedVehicles>
<F>                     <!-- attributes legend -->
<RS> 
    <R>
        <VS>
            <V />       <!-- vehicle -->
            <V />       <!-- vehicle -->
        </VS>
    </R>
</RS>
</F>
</CompressedVehicles>

Then, there are other system nodes not useful in this example: <ErrorMessage/>...

Basically, converting a XML in JSON format using SimpleXML can be a very simple task:

$xml  = simplexml_load_string( $xmlString );
$json = json_encode( $xml );

By this easy way, you obtain in $json variable a JSON string like this:

{
    "CompressedVehicles": {
        "F": {
            "@attributes": { ... },
            "RS": {
                "R": {
                    "@attributes": { "_ID": "9002250" },
                    "VS": {
                        "V": [
                            {
                                "@attributes": { ... }
                            },
                            {
                                "@attributes": { ... }
                            }
                        ]
                    }
                }
            }
        }
    },
    "ErrorMessage": {},
    "InventoryResultType": "OK",
    "IsSuccess": "true"
}

pastebin complete JSON

Re-decoding it:

$data = json_decode( $json );

you can add/modify/delete/print various elements using standard php syntax for objects and array.

So, i.e., following two lines:

echo $data->CompressedVehicles->F->{'@attributes'}->_0) . PHP_EOL;
echo $data->CompressedVehicles->F->{'@attributes'}->_1) . PHP_EOL;

will output:

vin
stock

Otherwise, if you want access to vehicles data, you can do it through a foreach loop:

foreach( $data->CompressedVehicles->F->RS->R->VS->V as $vehicle )
{
    echo $vehicle->{'@attributes'}->_0 . PHP_EOL;
    echo $vehicle->{'@attributes'}->_1 . PHP_EOL;
}

output:

WA1CMAFP3FA096506
A096506
WAU3GAFD2FN030313
A030313

Creating a custom JSON using SimpleXML

A (bit) more complex operation can be to obtain your desired JSON, especially due the weird structure of XML, that use codified attributes.

After loading your XML string:

$xml = simplexml_load_string( $xmlString );

you can navigate in the XML structure. The SimpleXML syntax is very similar to php StdObject syntax: to select a node level you have to use ->nodeName; to access to a single node as same level you can use array syntax (->nodeName[0]); to access to a specific attribute node you can use array syntax (->nodeName[0]['attributeName']).

So, to select <CompressedVehicles> node with all its children:

$CompressedVehicles = $xml->CompressedVehicles;

To echo a node as XML:

echo $CompressedVehicles->F->RS->R->VS->V[0]->asXML();
#                                         ↑ only first vehicle

output:

<V _0="WA1CMAFP3FA096506" _1="A096506" _2="54305" _3="New" ... />

As mentioned before, you have to create a legend for attributes, that are listed in <F> node:

<F _0="vin" _1="stock" _2="msrp" _3="type" _4="year" _5="make" _6="model" _7="imagelist" _8="stockimage"> 

To do this, you can fill an array iterating <F> node attributes:

$attributes = array();
foreach( $CompressedVehicles->F->attributes() as $key => $val )
{
    $attributes[$key] = $val->__toString();
}

Now, in $attributes array, you have this:

Array
(
    [_0] => vin
    [_1] => stock
    [_2] => msrp
    [_3] => type
    [_4] => year
    [_5] => make
    [_6] => model
    [_7] => imagelist
    [_8] => stockimage
)

It's the moment to init the main array:

$data = array();

Then you can perform a foreach loop through all <V> nodes and fill a sub-array using the keys from $attributes:

foreach( $CompressedVehicles->F->RS->R->VS->V as $vehicle )
{
    $line = array();
    foreach( $vehicle->attributes() as $key => $val )
    {
        $line[$attributes[$key]] = $val->__toString();
    }

While you're at it, why don't explode images element?

    $line['imagelist'] = explode( '|', $line['imagelist'] );

At this point, you can add sub-array to main array:

    $data[] = $line;
}

You can note the ->__toString() syntax to cast a SIMPLEXMLElement object to string.

Now, in your $data you have this:

Array
(
    [0] => Array
        (
            [vin] => WA1CMAFP3FA096506
            [stock] => A096506
            [msrp] => 54305
            [type] => New
            [year] => 2015
            [make] => Audi
            [model] => Q5
            [imagelist] => Array ( ... )
            [stockimage] => 
        )
    [1] => Array ( ... )
)

pastebin complete array structure

And you can encode it in a JSON string format:

$json = json_encode( $data );

$json contains (prettified):

[
    {
        "vin": "WA1CMAFP3FA096506",
        "stock": "A096506",
        "msrp": "54305",
        "type": "New",
        "year": "2015",
        "make": "Audi",
        "model": "Q5",
        "imagelist": [
            "http:\/\/content.homenetiol.com\/640x480\/53ef04aa3c46463aaa4fd91b13c00037.jpg",
            ...
        ],
        "stockimage": ""
    },
    {
        "vin": "WAU3GAFD2FN030313",
        ...
    }
]

pastebin complete JSON

fusion3k
  • 11,568
  • 4
  • 25
  • 47
  • This is awesome -- thank you for taking the time to explain EVERYTHING in detail -- works like a champ. – proph3t Apr 07 '16 at 16:36
  • What if the following applies: ` ` Where multiple `` entries are present? – proph3t Apr 19 '16 at 21:51
  • Just iterate through ``. Note that that must be a new question. ...But I am sure that with a little effort you can find the way by yourself! The mechanism doesn't change, you have only to iterate different levels. :) – fusion3k Apr 19 '16 at 22:23