0

I have tried various methods as seen in here and in here and many more.

I even tried the function in here.

The XML looks something like this:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://tempuri.org/IFooEntryOperation/SaveFooStatusResponse</a:Action></s:Header><s:Body><SaveFooStatusResponse xmlns="http://htempuri.org/"><SaveFooStatusResult xmlns:b="http://schemas.datacontract.org/2004/07/FooAPI.Entities.Foo" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><b:AWBNumber>999999999</b:AWBNumber><b:IsError>true</b:IsError><b:Status><b:FooEntryStatus><b:StatusCode>Foo_ENTRY_FAILURE</b:StatusCode><b:StatusInformation>InvalidEmployeeCode</b:StatusInformation></b:FooEntryStatus></b:Status></SaveFooStatusResult></SaveFooStatusResponse></s:Body></s:Envelope>

And here's one example of my code (I have a dozen variations):

$ReturnData = $row["ReturnData"]; // string frm a database
if (strpos($ReturnData, "s:Envelope") !== false){
    $ReturnXML = new SimpleXMLElement($ReturnData);
    $xml = simplexml_load_string($ReturnXML);
    $StatusCode = $xml["b:StatusCode"];
    echo "<br>StatusCode: " . $StatusCode;
    $IsError = $xml["b:IsError"];
    echo "<br>IsError: " . $IsError;
}

Another option I tried:

$test = json_decode(json_encode($xml, 1); //this didn't work either

I either get an empty array or I get errors like:

"Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML"

I have tried so many things, I may lost track of where my code is right now. Please help - I am really stuck...

I also tried:

$ReturnXML = new SimpleXMLElement($ReturnData);
    foreach( $ReturnXML->children('b', true)->entry as $entries ) {
        echo (string) 'Summary: ' . simplexml_load_string($entries->StatusCode->children()->asXML(), null, LIBXML_NOCDATA) . "<br />\n";
    }
2
  • You know that pod or b is a namespace, right? Commented Apr 29, 2019 at 7:24
  • @u_mulder yes, I tried declaring a namespace, but that didn't help. Commented Apr 29, 2019 at 7:58

2 Answers 2

1

Method 1.

You can try the below code snippet to parse it an array

$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $values, $indexes);// $xml containing the XML
xml_parser_free($p);
echo "Index array\n";
print_r($indexes);
echo "\nVals array\n";
print_r($values);

Method 2.

function XMLtoArray($xml) {
  $previous_value = libxml_use_internal_errors(true);
  $dom = new DOMDocument('1.0', 'UTF-8');
  $dom->preserveWhiteSpace = false; 
  $dom->loadXml($xml);
  libxml_use_internal_errors($previous_value);
  if (libxml_get_errors()) {
    return [];
  }
  return DOMtoArray($dom);
}
function DOMtoArray($root) {
  $result = array();
  if ($root->hasAttributes()) {
     $attrs = $root->attributes;
     foreach ($attrs as $attr) {
         $result['@attributes'][$attr->name] = $attr->value;
     }
  }
  if ($root->hasChildNodes()) {
    $children = $root->childNodes;
    if ($children->length == 1) {
        $child = $children->item(0);
        if (in_array($child->nodeType,[XML_TEXT_NODE,XML_CDATA_SECTION_NODE])) 
        {
            $result['_value'] = $child->nodeValue;
            return count($result) == 1
                ? $result['_value']
                : $result;
        }
    }
    $groups = array();
    foreach ($children as $child) {
        if (!isset($result[$child->nodeName])) {
            $result[$child->nodeName] = DOMtoArray($child);
        } else {
            if (!isset($groups[$child->nodeName])) {
                $result[$child->nodeName] = array($result[$child->nodeName]);
                $groups[$child->nodeName] = 1;
            }
            $result[$child->nodeName][] = DOMtoArray($child);
        }
    }
}
  return $result;
}

You can get an array using print_r(XMLtoArray($xml));

Sign up to request clarification or add additional context in comments.

1 Comment

Method 1 worked for me and because I like simple and short and I associate that with elegant code (or perhaps because I'm lazy), I didn't go beyond that. Thanx!
1

I don't know how you would do this using SimpleXMLElement but judging by the fact you have tried so many things I trust that the actual method employed is not important so you should therefore find the following, which uses DOMDocument and DOMXPath, of interest.

        /* The SOAP response */
        $strxml='<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://tempuri.org/IFooEntryOperation/SaveFooStatusResponse</a:Action>
    </s:Header>
    <s:Body>
        <SaveFooStatusResponse xmlns="http://htempuri.org/">
            <SaveFooStatusResult xmlns:b="http://schemas.datacontract.org/2004/07/FooAPI.Entities.Foo" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                <b:AWBNumber>999999999</b:AWBNumber>
                <b:IsError>true</b:IsError>
                <b:Status>
                    <b:FooEntryStatus>
                        <b:StatusCode>Foo_ENTRY_FAILURE</b:StatusCode>
                        <b:StatusInformation>InvalidEmployeeCode</b:StatusInformation>
                    </b:FooEntryStatus>
                </b:Status>
            </SaveFooStatusResult>
        </SaveFooStatusResponse>
    </s:Body>
</s:Envelope>';

        /* create the DOMDocument and manually control errors */
        libxml_use_internal_errors( true );
        $dom=new DOMDocument;
        $dom->validateOnParse=true;
        $dom->recover=true;
        $dom->strictErrorChecking=true;
        $dom->loadXML( $strxml );
        libxml_clear_errors();

        /* Create the XPath object */
        $xp=new DOMXPath( $dom );
        /* Register the various namespaces found in the XML response */
        $xp->registerNamespace('b','http://schemas.datacontract.org/2004/07/FooAPI.Entities.Foo');
        $xp->registerNamespace('i','http://www.w3.org/2001/XMLSchema-instance');
        $xp->registerNamespace('s','http://www.w3.org/2003/05/soap-envelope');
        $xp->registerNamespace('a','http://www.w3.org/2005/08/addressing');

        /* make XPath queries for whatever pieces of information you need */
        $Action=$xp->query( '//a:Action' )->item(0)->nodeValue;
        $StatusCode=$xp->query( '//b:StatusCode' )->item(0)->nodeValue;
        $StatusInformation=$xp->query( '//b:StatusInformation' )->item(0)->nodeValue;


        printf(
            "<pre>
            %s
            %s
            %s
            </pre>",
            $Action,
            $StatusCode,
            $StatusInformation
        );

The output from the above:

    http://tempuri.org/IFooEntryOperation/SaveFooStatusResponse
    Foo_ENTRY_FAILURE
    InvalidEmployeeCode

1 Comment

This looks interesting but I chose Method 1 by @rakesh-jakkar since it is the shortest. Still, you got an upvote. :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.