提问人:Mohib Salahuddin Ayubi 提问时间:2/24/2023 最后编辑:ThWMohib Salahuddin Ayubi 更新时间:2/25/2023 访问量:93
XML 不使用 soap-env 解析,在 PHP 中具有自定义标签
XML not parse with soap-env having custom tags in PHP
问:
我在 PHP 中解析我的 XML 响应时遇到错误
当我从CURL请求调用时,我有下面的XML响应
<?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<eb:MessageHeader xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" eb:version="1.0" soap-env:mustUnderstand="1">
<eb:From>
<eb:PartyId eb:type="URI">Sabre_API</eb:PartyId>
</eb:From>
<eb:To>
<eb:PartyId eb:type="URI">Agency</eb:PartyId>
</eb:To>
<eb:ConversationId>2021.01.DevStudio</eb:ConversationId>
<eb:Service eb:type="sabreXML">Session</eb:Service>
<eb:Action>TokenCreateRS</eb:Action>
<eb:MessageData>
<eb:MessageId>1913771794839350290</eb:MessageId>
<eb:Timestamp>2023-02-23T22:04:43</eb:Timestamp>
</eb:MessageData>
</eb:MessageHeader>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:BinarySecurityToken valueType="String" EncodingType="wsse:Base64Binary">T1RLAQLASo74A7olKG7QnepeFqs19UHX+0Cds9QiDZoYfu677xC3Vkr9a+OcQhutjPL4atVMAADQRtHIXdehGg/0OVuPdia/0cM233jFDvyJJHgJHC3o8gV2ssS63b4Y0lgCG59SiG4tmEcqAXcYAMlnq+wJ4TfsOIDFwYdP+D0peSEFBM/m3EyOUqc4idJ+vO4S7xENCeQ7UX4YVKjVLJs788omPDbSIRNo85KQ5QxRprldV0jucJpAtbNfs1DrMHFqNIPyg0CpVpgXILkFx0azkcAuvmbHMHLqqO13WJEOhsG0KDBhBhRn8CwoCgD9foXL24W6yGu8Ecm0Fzvb/MuAjuYm9s48yg**</wsse:BinarySecurityToken>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<sws:TokenCreateRS xmlns:sws="http://webservices.sabre.com" Version="1.0.0">
<sws:Success/>
</sws:TokenCreateRS>
</soap-env:Body> </soap-env:Envelope>
为了解析上述 XML,我最初尝试使用simplexml_load_String,但它给出了一个空响应。
然后我使用以下代码尝试了 DOM 方法,这里考虑到 $response->Data 是上面的 XML。
$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->loadXML($response->Data);
$dom->formatOutput = true;
$XMLContent = $dom->saveXML();
它再次给了我以下输出:
<!--?xml version="1.0" encoding="UTF-8"?-->
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:header>
<eb:messageheader xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" eb:version="1.0" soap-env:mustunderstand="1">
<eb:from>
<eb:partyid eb:type="URI">Sabre_API</eb:partyid>
</eb:from>
<eb:to>
<eb:partyid eb:type="URI">Agency</eb:partyid>
</eb:to>
<eb:conversationid>2021.01.DevStudio</eb:conversationid>
<eb:service eb:type="sabreXML">Session</eb:service>
<eb:action>TokenCreateRS</eb:action>
<eb:messagedata>
<eb:messageid>1002038859236010450</eb:messageid>
<eb:timestamp>2023-02-23T23:52:03</eb:timestamp>
</eb:messagedata>
</eb:messageheader>
<wsse:security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:binarysecuritytoken valuetype="String" encodingtype="wsse:Base64Binary">T1RLAQJZqih4+TYQmYCcdj42lcej5nckNWdo6WNb8edNl3xNtxAkqmu2YKjKki1OKQ7B3HK3AADQCGiRWrlzFPM0KB4foAOsSF+I+5eXE32uQ23LLd+hOduY2BCJYqPw7CvwCJ/LfNjy3P+QyvClvu6ysctC3a0GjmixDPDqCIckcXPb+XDFyYhR5G5QzQjch/Eax25koLnNvfN8rlvjNq+ENJmaV17wP43GLo1pzd19d9HGMn1VgjrJiVGWAb1ezyeiFNAd1VuBD2lAmdlo4jvZJzAS/fklZvwNFbKME64YpaFRptoLz0FKmz47y1TVYFtV6TZxbKirP3PDms0aGlItbJ4apPSB2Q**</wsse:binarysecuritytoken>
</wsse:security> </soap-env:header> <soap-env:body>
<sws:tokencreaters xmlns:sws="http://webservices.sabre.com" version="1.0.0">
<sws:success>
</sws:success></sws:tokencreaters> </soap-env:body> </soap-env:envelope>
所以我计划从NODE获取数据,如下所示
$XMLContent->getElementsByTagName('soap-env:header')->item(0)->nodeValue);
但是,它没有给我一个节点值,而是开始给我和错误。
我只想获取节点中的数据wsse:binarysecuritytoken
有没有人经历过这样的事情?
你能帮帮我吗??
更新也尝试了以下操作,但仍然没有帮助
$domDocument = new DOMDocument();
$domDocument->loadXML($XMLContent);
$carriers=array();
$results=$domDocument->getElementsByTagName("wsse:Security");
foreach($results as $result)
{
foreach($result->childNodes as $node)
{
if($node instanceof DOMElement)
{
array_push($carriers, $node->textContent);
}
}
}
var_dump($carriers);
答:
好的,终于花了几个小时,我明白了! 我必须根据标签名称进行修改,如下所示,在大多数父级中,我不得不使用 soap-env 而不是 SOAP。
$dom = new DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->loadXML($response->Data);
$dom->formatOutput = true;
$XMLContent = $dom->saveXML();
$xml = simplexml_load_String($XMLContent, null, null, 'soap-env', true);
if(!$xml)
trigger_error("Encoding Error!", E_USER_ERROR);
$Results = $xml->children('soap-env',true);
foreach($Results->children('soap-env',true) as $fault){
if(strcmp($fault->getName(),'Fault') == 0){
trigger_error("Error occurred request/response processing!", E_USER_ERROR);
}
}
foreach($Results->children('wsse',true) as $nodes){
if(strcmp($nodes->getName(),'Security') == 0){
foreach($nodes->children('wsse',true) as $securityNodes){
if(strcmp($securityNodes->getName(),'BinarySecurityToken') == 0){
$tokenParsed = (string)$securityNodes;
}
}
}
}
这是 SOAP,一种使用 XML 语法的对象序列化格式。最好的解决方案是使用 SOAP 库。PHP对此有帮助。使用 XML 库会低一个级别。ext/soap
XML 使用命名空间。命名空间使用唯一的 URI 指定。为了实现可读性/可维护性,XML 定义了 URI 的别名,并将其用作节点名称的前缀。但是,以下 3 个示例都应理解为:{http://schemas.xmlsoap.org/soap/envelope/}Envelope
<soap-env:envelope xmlns::soap-env="http://schemas.xmlsoap.org/soap/Envelope/"/>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"/>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"/>
命名空间可以在任何元素节点上定义,因此即使在单个文档中也可以更改它们。这意味着您的代码不应依赖于文档中的别名/前缀,而是依赖于命名空间 URI。
我强烈建议为使用的命名空间定义一个数组变量/常量。然后,您可以使用 Xpath 和命名空间感知 DOM 方法(带有后缀)。NS
// used namespaces, the keys do NOT need to match the prefixes in the XML.
$xmlns = [
'soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
'eb' => 'http://www.ebxml.org/namespaces/messageHeader',
'sec' => 'http://schemas.xmlsoap.org/ws/2002/12/secext'
];
$document = new DOMDocument();
$document->loadXML(getSoapXmlString());
$xpath = new DOMXpath($document);
// register your aliases for the namespaces
foreach ($xmlns as $alias => $uri) {
$xpath->registerNamespace($alias, $uri);
}
$token = $xpath->evaluate(
'string(//sec:Security/sec:BinarySecurityToken)'
);
var_dump($token);
DOMXpath::evaluate()
允许返回节点列表和标量值的 Xpath 表达式。如果将节点列表(由位置路径指定)强制转换为字符串,它将返回第一个节点的文本内容或空字符串。
评论