无法在Yii2中将Soap响应字符串转换为xml

时间:2019-05-04 06:15:40

标签: php xml curl soap

我有一个肥皂要求。我能够发送请求并获得字符串响应。现在,我想将其转换为XML并从中获取所需的数据。

回复

string(1383) "
<?xml version="1.0" encoding="UTF-8"?>
<ResponseMessage xmlns:ns="http://iec.ch/TC57/2011/schema/message" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://iec.ch/TC57/2011/schema/message Message.xsd">
<Header>
    <Verb>reply</Verb>
    <Noun>EndDeviceControls</Noun>
    <Revision>2.0</Revision>
    <Timestamp>2019-05-04T10:39:11+04:30</Timestamp>
    <Source>HES-BSTC</Source>
    <AsyncReplyFlag>true</AsyncReplyFlag>
    <ReplyAddress>http://ip:port/AmiWeb/services/Metering</ReplyAddress>
    <User>
        <UserID>user</UserID>
    </User>
    <MessageID>6C3F761B-A1EC-4EBE-BB49-67B720C5AE62</MessageID>
    <CorrelationID>1001</CorrelationID>
    <Property>
        <Name>password</Name>
        <Value>password</Value>
    </Property>
    <Property>
        <Name>timeout(m)</Name>
        <Value>30</Value>
    </Property>
</Header>
<Reply>
    <Result>OK</Result>
    <Error>
        <code>0.3</code>
    </Error>
</Reply>
</ResponseMessage>"

代码

$xml_post_string = /** @lang text */
                           '<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:soap="http://soap.inf.hexing.cn">
<soapenv:Header/>
<soapenv:Body>
  <soap:doCommand>
     <!--Optional:-->
     <arg0><![CDATA[<?xml version="1.0" encoding="utf-8"?>
<RequestMessage
xmlns="http://iec.ch/TC57/2011/schema/message"
xmlns:m="http://iec.ch/TC57/2011/EndDeviceControls#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://iec.ch/TC57/2011/schema/message Message.xsd">
<Header>
<Verb>create</Verb>
<Noun>EndDeviceControls</Noun>
<Revision>2.0</Revision>
<Timestamp>2016-01-01T00:00:00+04:30</Timestamp>
<Source>MDM</Source>
<AsyncReplyFlag>true</AsyncReplyFlag>
<ReplyAddress>http://ip:port/AmiWeb/services/Metering</ReplyAddress>
<AckRequired>true</AckRequired>
<User>
<UserID>'.$userName.'</UserID>
</User>
<MessageID>83c643e6-85c5-43c0-9e0a-fa1deb469b72</MessageID>
<CorrelationID>1001</CorrelationID>
<Property>
<Name>password</Name>
<Value>'.$password.'</Value>
</Property>
<Property>
<Name>timeout(m)</Name>
<Value>30</Value>
</Property>
</Header>
<Payload>
<m:EndDeviceControls>
<m:EndDeviceControl>
<m:reason>Disconnect/Reconnect</m:reason>
<m:EndDeviceControlType ref="3.0.211.23"/>
<m:EndDevices>
<m:mRID>'.$msn.'</m:mRID>
<m:Names>
<m:name>Disconnect</m:name>
<m:NameType>
<m:name>ControlType</m:name>
</m:NameType>
</m:Names>
</m:EndDevices>
</m:EndDeviceControl>
</m:EndDeviceControls>
</Payload>
</RequestMessage>
     ]]></arg0>
  </soap:doCommand>
 </soapenv:Body>
</soapenv:Envelope>';
 $headers = array(
                           "Content-type: text/xml;charset=\"utf-8\"",
                           "Accept: text/xml",
                           "Cache-Control: no-cache",
                           "Pragma: no-cache",
                           //"SOAPAction: http://connecting.website.com/WSDL_Service/GetPrice",
                           "Content-length: ".strlen($xml_post_string),
                       ); //SOAPAction: your op URL

                       $url = $soapUrl;

                       // PHP cURL  for https connection

                       $ch = curl_init();
                       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
                       curl_setopt($ch, CURLOPT_URL, $url);
                       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                       curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
                       curl_setopt($ch, CURLOPT_TIMEOUT, 10);
                       curl_setopt($ch, CURLOPT_POST, true);
                       curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string); // the SOAP request
                       curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

                       // converting
                       $response = curl_exec($ch);
                       curl_close($ch);
                       $xml = simplexml_load_string($response);
                       var_dump($xml);
                       die();

输出

object(SimpleXMLElement)#121 (0) { }

输出为空。现在我想要两件事

  1. 将字符串转换为XML
  2. 从返回的XML中,我想从响应中获取<AsyncReplyFlag>true</AsyncReplyFlag>的值

更新1

根据建议,我添加了以下代码

$xml = simplexml_load_string($response);
                        echo $xml->asXML();

输出

<?xml version="1.0" encoding="UTF-8"?>
<ResponseMessage xmlns:ns="http://iec.ch/TC57/2011/schema/message" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://iec.ch/TC57/2011/schema/message Message.xsd">
<Header>
    <Verb>reply</Verb>
    <Noun>EndDeviceControls</Noun>
    <Revision>2.0</Revision>
    <Timestamp>2019-05-04T14:01:48+04:30</Timestamp>
    <Source>HES-BSTC</Source>
    <AsyncReplyFlag>true</AsyncReplyFlag>
    <ReplyAddress>http://ip:port/AmiWeb/services/Metering</ReplyAddress>
    <User>
        <UserID>user</UserID>
    </User>
    <MessageID>F4E15012-D009-4CBC-A610-E937F2620193</MessageID>
    <CorrelationID>1001</CorrelationID>
    <Property>
        <Name>password</Name>
        <Value>password</Value>
    </Property>
    <Property>
        <Name>timeout(m)</Name>
        <Value>30</Value>
    </Property>
</Header>
<Reply>
    <Result>OK</Result>
    <Error>
        <code>0.3</code>
    </Error>
</Reply>
</ResponseMessage>

我尝试了什么?

$xml = new SimpleXMLElement($response);
print_r($xml);
die();

它给了我一个空洞的结果

 $doc = new DOMDocument('1.0', 'utf-8');
                       $doc->loadXML($response);
                       $XMLresults = $doc->getElementsByTagName("AsyncReplyFlag")->item(0)->textContent;
                       echo $XMLresults;
                       die();

这给我一个错误

  

试图获取非对象的属性   $ XMLresults = $ doc-> getElementsByTagName(“ AsyncReplyFlag”)-> item(0)-> textContent;

仍然,我无法获得<AsyncReplyFlag>true</AsyncReplyFlag>的值

如何实现? 任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

尝试使用var_dump()输出SimpleXMLElement并不是一个好主意,而且正如您所看到的-付出不了多少。

如果您只想查看已加载的XML,请使用...

echo $xml->asXML();

这将向您显示XML已加载好,因此输出您的字段仅是

$xml = simplexml_load_string($response);
echo $xml->Header->AsyncReplyFlag;

答案 1 :(得分:1)

作为一个简单的文档,DOMDocument提取它应该没有问题:

echo (@DOMDocument::loadXML($response))->getElementsByTagName("AsyncReplyFlag")->item(0)->textContent;

...或者如果您想仔细检查每一步的错误,

$xml_errors=[];
set_error_handler(function(int $errno, string $errstr, string $errfile, int $errline, array $errcontext) use(&$xml_errors){
    ob_start();
    call_user_func_array('var_dump',func_get_args());
    $xml_errors[]=ob_get_clean();
});
$domd=new DOMDocument();
$loaded=$domd->loadXML($response);
restore_error_handler();
if(!$loaded){
    if(defined('STDERR')){
        fprintf(STDERR,"%s",$response);
    }
    throw new \RuntimeException("errors parsing XML! xml printed in stderr, parsing errors: ".print_r($xml_errors,true));    
}
$ele=$domd->getElementsByTagName("AsyncReplyFlag");
if($ele->length<1){
    if(defined('STDERR')){
        fprintf(STDERR,"%s",$response);
    }
    throw new \RuntimeException("did not get AsyncReplyFlag in response! (xml printed in stderr)");
}
echo $ele->item(0)->textContent;

答案 2 :(得分:0)

使用XPath查询

$xml = new SimpleXMLElement($xmlData);
echo $xml->xpath('//AsyncReplyFlag')[0];

OR

您可以使用xml_parser_create

$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $values, $indexes);// $xml containing the XML
xml_parser_free($p);

echo $values[12]['value'];

有关其他详细信息,您可以print_r($values)