【问题标题】:Modifying sent XML on server side with PHP's SOAP使用 PHP 的 SOAP 在服务器端修改发送的 XML
【发布时间】:2023-03-11 19:38:01
【问题描述】:

关于PHP的SoapClient和SoapServer,WSDL模式的问题。

比方说,我需要为 XML 的某个部分创建一个摘要,其中包含其中的数据。使用 SoapClient 很容易。我从类SoapClient 重载__doRequest() 方法,对某些元素进行散列并将其作为<Hash></Hash> 中的元素<SOAP-ENV:Header/> 附加。 然后我将生成的 XML 发送到调用 parent::__doRequest() 的 SOAPServer。

我需要对响应 XML 做同样的事情。在服务器方面,我遇到了困难。似乎服务器只能将数据作为嵌套数组或对象发送,并且以某种方式插入到客户端的响应 XML 中。我尝试使用SoapServer 的响应发送 XML,然后它返回空 XML。

我真的需要在服务器端解析和修改 XML(制作哈希、数字签名等),但到目前为止,无论我在哪里搜索,我都没有找到答案,所以我真的很感激你帮助。谢谢。

【问题讨论】:

  • 我也想知道。请参阅我的问题http://stackoverflow.com/questions/12692797/how-do-i-catch-data-from-the-xml-content-of-a-soap-request-in-a-php-soapserver,我在其中询问如何从输入 XML 中获取数据(这似乎是在stdClass 对象上强制转换的),当然还返回一些 XML(可能是输入的,但可以根据需要进行修改)做) - 但我在任何地方都找不到任何有用的东西。希望您的问题得到解答!
  • 我取得了一些进展。从输入中获取数据首先使用file_get_contents ('php://input'),请参阅http://stackoverflow.com/questions/10835336/parsing-soap-response-via-wsdl-soapserver/10955907#10955907。但是我仍然无法按照我的意愿创建返回 XML - 我得到了一些似乎由 soapServer 生成的标准返回值,使用 WSDL 中的 defs 但奇怪的是没有返回消息中指定的顶级,而是名称等于输入一+“响应”。当我发现如何做到这一点时,我会告诉你的。
  • @Maestro13 是的,谢谢 - 我用这个问题link 帮助我从客户端解析 XML,但仍然不知道如何在服务器端创建和修改 XML。我想我们可以解决我们的两个问题,让我们讨论一下,只需将您的任何联系信息通过电子邮件发送给 supervodka (at) gmail dot com,谢谢:)

标签: php soap soapserver


【解决方案1】:

您必须获得一个没有 XML 声明的 XML 字符串,并使用 SoapVar 对其进行解析。
详情请见how-return-custom-xml-response-in-soapserver-response

简而言之,就是这样。
您从输入和需要放入其中的任何其他内容构造一个 DOMDocument。 XSLT 是解析和更改 XML 的好方法(有关如何在 php 中使用 xslt 的简单示例,请再次参见上面的链接)。
然后从您希望返回的DOMDocument 中选择DOMNode,并使用此节点作为参数应用saveXML。这会将所需的 XML 保存为字符串没有声明。没有参数的普通saveXML() 会将根节点保存为字符串包括声明。 因此:

$nodes = $dom -> getElementsByTagName ('chooseTheElementYouWishToReturn');
$node = $nodes -> item(0);

$result = new SoapVar ($dom -> saveXML($node), XSD_ANYXML);
return ($result);

当然,当您希望返回根元素时,这也可以:

$result = new SoapVar ($dom -> saveXML($dom -> documentElement), XSD_ANYXML);
return ($result);

添加

我注意到您希望在 SOAP 标头而不是正文中添加一些内容。
这也有点棘手,但可以实现 - 我希望以下内容能满足您的需求。

首先,添加头部细节只能在函数脚本内完成,然后函数必须将服务器变量声明为全局变量,以便引用全局(函数外部)声明的变量,如下:

<?php   
    class mySOAPclass {
        function xxx ($arg) {
            global $server;

            // your code for the header part
            // example
            $auth = array();
            $auth['UserName'] = 'user';
            $auth['Password'] = 'pw';
            $header = new SoapVar ($auth, SOAP_ENC_OBJECT);
            // end example

            $header = new SoapHeader ('http://schemas.xmlsoap.org/soap/header/', 'credentials', $header, false);
            $server -> addSoapHeader ($header);

            // your code for the body part, assuming it results in a DOM $dom

            $result = new SoapVar ($dom -> saveXML($dom -> documentElement), XSD_ANYXML);

            return ($result);
        }

    ini_set( "soap.wsdl_cache_enabled", "0");
    $server = new SoapServer ("yourOwn.wsdl");
    $server -> setClass ('mySOAPclass');
    $server -> setObject (new mySOAPclass());
    $server -> handle();
?>

注意,需要先从数组中构造一个SoapVar;如果将数组直接提供给标题,则会得到丑陋的项目/键和项目/值节点。

以上导致如下返回结构:

<SOAP-ENV:Envelope 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="http://schemas.xmlsoap.org/soap/header/">
    <SOAP-ENV:Header>
        <ns1:credentials>
            <UserName>user</UserName>
            <Password>pw</Password>
        </ns1:credentials>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        ...
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

【讨论】:

  • SoapVar 类的对象无法转换为字符串
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
相关资源
最近更新 更多