将XML嵌入SOAP/PHP编码低于和大于符号

将XML嵌入SOAP/PHP编码低于和大于符号,php,soap,Php,Soap,我们有一个包含以下内容的WSDL,并使用PHP的标准SOAP客户端进行调用: <element name="doSomething"> <complexType> <sequence> <element name="Payload" nillable="true" type="xsd:string"/> <element name="Username" type="str

我们有一个包含以下内容的WSDL,并使用PHP的标准SOAP客户端进行调用:

<element name="doSomething">
    <complexType>
        <sequence>
            <element name="Payload" nillable="true" type="xsd:string"/>
            <element name="Username" type="string"/>
            <element name="service" type="string"/>
            <element name="Password" type="string"/>
        </sequence>
    </complexType>
</element>
现在,SOAP客户端的请求通过
echo$client->\uuu getLastRequest()转储;
如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="pa/WebshopService"><SOAP-ENV:Body><ns1:doSomething><ns1:Payload>&lt;code&gt;
1
&lt;/code&gt;
</ns1:pcRequest><ns1:Username>bar</ns1:Username><ns1:service>bar</ns1:service><ns1:Password>bar</ns1:Password></ns1:doSomething></SOAP-ENV:Body></SOAP-ENV:Envelope>
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="pa/WebshopService"><SOAP-ENV:Body><ns1:doSomething><ns1:Payload><code>
1
</code>
</ns1:pcRequest><ns1:Username>bar</ns1:Username><ns1:service>bar</ns1:service><ns1:Password>bar</ns1:Password></ns1:doSomething></SOAP-ENV:Body></SOAP-ENV:Envelope>
  • 如何使用PHP SoapClient发送这样的消息
  • 在这种情况下WSDL是否有效

复杂类型
doSomething
表示,属性
有效负载
是字符串类型。因此,xml内容的编码字符串应该是正确的。如果提供方希望内容未编码,则属性
有效负载将是另一种复杂类型。因此,在这种情况下,wsdl是无效的,如果它是真的,那么提供者端确实需要一个元素而不是一个编码字符串

无论如何,有一个解决方案可以用PHP处理。只需处理
有效负载
而不是作为字符串。取而代之的是把它做成一个复杂的类型

class DoSomething()
{
    protected $Payload;

    protected $Username;

    protected $Service;

    protected $Password;

    public function getPayload() : ?\SoapVar        {
        return $this->Payload;
    }

    public function setPayload(\SoapVar $payload) : DoSomething
    {
        $this->Payload = $payload;
        return $this;
    }

    ...

    public function encode() : \SoapVar
    {
        return new \SoapVar(
            $this,
            SOAP_ENC_OBJECT,
            null,
            null,
            'doSomething',
            'http://www.example.com/namespace'
        );
    }
}
在上面,您可以看到复杂类型
doSomething
是一个PHP类。您还可以看到示例getter和setter方法。get方法返回null或\SoapVar实例。setter方法采用\SoapVar实例

出于您的目的,您需要另一个PHP类来处理
Payload
属性,该属性包含
code
属性

class Payload
{
    protected $Code;

    public function getCode() : ?\SoapVar
    {
        return $this->Code;
    }

    public function setCode(\SoapVar $code) : Payload
    {
        $this->Code = $code;
        return $this;
    }

    public function encode() : \SoapVar
    {
        return new \SoapVar
        {
            $this,
            SOAP_ENC_OBJECT,
            null,
            null,
            'Payload',
            'http://www.example.com/namespace'
        }
    }
}
现在把所有的东西放在一起

$code = new \SoapVar(1, XSD_INT, null, null, 'code');

$payload = (new Payload())
    ->setCode($code)
    ->encode();

$doSomething = (new DoSomething())
    ->setPayload($payload)
    ->setUsername(...)
    ->setService(...)
    ->setPassword(...)
    ->encode();

$result = $client->doSomething($doSomething);
现在你的请求应该是

<ns1:doSomething>
    <ns1:Payload>
        <code>1</code>
    </ns1:Payload>
    <ns1:Username>...</ns1:Username>
    <ns1:Service>...</ns1:Service>
    <ns1:Password>...</ns1:Password>
</ns1:doSomething>

希望这对您有所帮助。

因此,在为代码属性初始化\SoapVar类时,只需释放namspace参数即可。我已经用这种方式编辑了我的答案。你会把这个解决方案称为“黑客”吗?我根本不会把它称为“黑客”。在您这边(消费者/php方面),这个解决方案是干净的,因为它都是原生php,没有变通方法或polyfill。使用未声明为干净的web服务解决提供者的问题是可以的。考虑一下,本地PHP SOAP客户端有一个类映射选项,您可以在这里列出所有WebService复杂类型。在实现soap客户机时,使用类和php自己提供的soap类是很自然的。
<ns1:doSomething>
    <ns1:Payload>
        <code>1</code>
    </ns1:Payload>
    <ns1:Username>...</ns1:Username>
    <ns1:Service>...</ns1:Service>
    <ns1:Password>...</ns1:Password>
</ns1:doSomething>