php - 在变成 simplexml 对象之前从响应中删除肥皂头
问题描述
我正在使用 Curl 来执行一个肥皂请求。现在看起来头中返回了一个错误,使我无法使用函数 simplexml_load_string 将返回的字符串转换为 simplexml 对象。您可以在下面找到 simplexml 函数中失败的响应部分:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><SOAP-ENV:Header><SOAP-SEC:Signature xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12"><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/><ds:Reference URI="#Body"><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>HV+/cOkUjNCdH5xuiLlGSHVgkUo=</ds:DigestValue></ds:Reference><ds:SignatureValue>MCwCFHXmoMrDUOScwMQ5g76OfxouICjBAhQtGKAorJLUQ0bA0UaKIe1gtmQPgA==</ds:SignatureValue></ds:SignedInfo></ds:Signature></SOAP-SEC:Signature></SOAP-ENV:Header><SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body">
有没有办法隔离肥皂正文内容并仅使用 simplexml_load_string 解析该部分?
在 curl 请求下方:
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"Content-length: ".strlen($xml_post_string),
);
$url = $soapUrl;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
$xml = simplexml_load_string(html_entity_decode($response), 'SimpleXMLElement', LIBXML_NOCDATA);
echo $xml->asXML();
if ($xml === false) {
echo "Failed to load XML: ";
foreach(libxml_get_errors() as $error) {
echo "<br>", $error->message;
}
} else {
var_dump($xml);
}
解决方案
我现在没有答案,但您首先需要将 curl 与 XML 处理分开。您应该首先从 curl 记录您的结果,并确保它是理智的并且符合您的期望。如果是,则继续解析它。curl 绝不应该以任何方式破坏/更改您的数据,但请求本身(标头等)可能会更改服务器的响应。
由于我无法验证您的服务器,因此我将不再使用您提供的内容。我已经关闭了<SOAP-ENV:Body>
标签并将 XML 转换为可读的,但除此之外它保持不变。此代码毫无问题地解析 XML,然后完全按预期发出它。
$response = <<<'TAG'
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Header>
<SOAP-SEC:Signature xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
<ds:Reference URI="#Body">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>HV+/cOkUjNCdH5xuiLlGSHVgkUo=</ds:DigestValue>
</ds:Reference>
<ds:SignatureValue>MCwCFHXmoMrDUOScwMQ5g76OfxouICjBAhQtGKAorJLUQ0bA0UaKIe1gtmQPgA==</ds:SignatureValue>
</ds:SignedInfo>
</ds:Signature>
</SOAP-SEC:Signature>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body"></SOAP-ENV:Body>
</SOAP-ENV:Envelope>
TAG;
$xml = simplexml_load_string(html_entity_decode($response), 'SimpleXMLElement', LIBXML_NOCDATA);
echo '<pre>';
print_r(htmlspecialchars($xml->asXML()));
echo '</pre>';
输出与输入完全相同,只是它包含 XML 指令并将 body 标记转换为自关闭:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Header>
<SOAP-SEC:Signature xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
<ds:Reference URI="#Body">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>HV+/cOkUjNCdH5xuiLlGSHVgkUo=</ds:DigestValue>
</ds:Reference>
<ds:SignatureValue>MCwCFHXmoMrDUOScwMQ5g76OfxouICjBAhQtGKAorJLUQ0bA0UaKIe1gtmQPgA==</ds:SignatureValue>
</ds:SignedInfo>
</ds:Signature>
</SOAP-SEC:Signature>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body"/>
</SOAP-ENV:Envelope>
所以以此为基准。在执行任何其他操作之前将您的 curl 响应写入文本文件,然后将该文本文件读回并执行逻辑。您对字符串 XML 应用的任何转换也应该被记录下来并进行比较,以确保它符合您的预期。在生产中你会跳过它,但这只是在调试过程中有所帮助。
另外,我不确定这有什么意义html_entity_decode
。如果您正在接收 XML(根据您的请求 mime 类型指定),那么它不应该应用任何转义序列,但也许您也有例外情况。
推荐阅读
- python - 从 csv 文件中删除所有具有特定值的行
- javascript - 嵌入 instagram HTML 帖子不显示图像
- android - 如何将 POST 请求从 Android 发送到 Elasticsearch
- c++ - OpenGL三角形总是白色的
- c++ - 表达式必须是 C++ 中的整数或无范围枚举类型?
- android - W/BiChannelGoogleApi:[FirebaseAuth:] getGoogleApiForMethod() 返回 Gms:com.google.firebase.auth.api.internal.zzal@5680b5b
- reactjs - 如何提高测试覆盖率 Jest, Enzyme
- html - 是否可以绕过使用所需属性、模式等的 html 验证
- jmeter - 如何在Jmeter中为非gui分布式负载测试传递堆参数?
- python - 如何在张量流中重用占位符?