Невозможно преобразовать строку ответа мыла в xml в Yii2 - PullRequest
1 голос
/ 04 мая 2019

У меня есть запрос на мыло.Я могу отправить запрос и получить ответ в виде строки.Теперь я хочу преобразовать его в 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();

Это дает мне ошибку

Попыткаполучить свойство необъекта*

Как мне этого добиться?Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

1 голос
/ 07 мая 2019

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;
1 голос
/ 04 мая 2019

Попытка вывести элемент SimpleXMLE с использованием var_dump() не очень хорошая идея, и, как вы видели, не дает много.

Если вы просто хотите увидеть загруженный XML, вместо этого используйте...

echo $xml->asXML();

, который покажет, что XML-файл загружен нормально, так что вывести поле после будет просто

$xml = simplexml_load_string($response);
echo $xml->Header->AsyncReplyFlag;
0 голосов
/ 04 мая 2019

Используя запрос XPath

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

ИЛИ

Вы можете использовать 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)

...