无法使用simplexml_load_string解析XML

时间:2019-04-29 07:20:05

标签: php simplexml-load-string

我尝试了各种方法,如here所示 here中还有更多内容。

我什至尝试了here中的函数。

XML看起来像这样:

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

这是我的代码的一个示例(我有十二种变体):

$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;
}

我尝试过的另一种选择:

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

我要么得到一个空数组,要么得到如下错误:

  

“致命错误:消息为'String'的未捕获异常'Exception'   无法解析为XML”

我已经尝试了很多事情,但我可能会忘记现在的代码位置。请帮忙-我真的被困住了...

我也尝试过:

$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 个答案:

答案 0 :(得分:1)

我不知道您将如何使用SimpleXMLElement来执行此操作,但是从您已经尝试了很多事情的事实来看,我相信所采用的实际方法并不重要,因此您应该找到以下内容,其中感兴趣的DOMDocumentDOMXPath

        /* 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
        );

上面的输出:

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

答案 1 :(得分:1)

方法1。

您可以尝试使用以下代码段将其解析为数组

$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);

方法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;
}

您可以使用print_r(XMLtoArray($xml));

获得一个数组