簡體   English   中英

PHP中的多個SOAP命名空間(在Python中解決)

[英]Multiple SOAP Namespaces in PHP (solved in Python)

我試圖在PHP中創建以下輸出:

    <?xml version="1.0" encoding="UTF-8"?>
    <SOAP-ENV:Envelope xmlns:ns0="http://webservices.company.co.uk/AddressMatching" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://webservices.company.co.uk/ServiceBase/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP-ENV:Header/>
       <ns1:Body>
          <ns0:GetAvailableAddresses>
             <ns0:request>
                <ns2:UserCredentials>
                   <ns2:AgentID>123</ns2:AgentID>
                   <ns2:Password>PASSword</ns2:Password>
                   <ns2:Username>user@company.com</ns2:Username>
                </ns2:UserCredentials>
                <ns0:Address>
                   <ns0:PostCode>NG42DJ</ns0:PostCode>
                </ns0:Address>
             </ns0:request>
          </ns0:GetAvailableAddresses>
       </ns1:Body>
    </SOAP-ENV:Envelope>

這在Python中相當容易,我正在使用的類(suds)只是讀取wsdl文件,並正確使用名稱空間:

    from suds.client import Client

    client = Client('/the/path/to/AddressMatchingService.wsdl')

    creds = { 'AgentID': '123', 'Username': 'user@company.com', 'Password': 'PASSword' }

    address = client.factory.create('Address')
    address.PostCode = "NG42DJ"

    address_request = client.factory.create('AvailableAddressesRequest')
    address_request.UserCredentials = creds
    address_request.Address = address

    request = client.service.GetAvailableAddresses(address_request)
    print request

無需引用與名稱空間有關的任何內容,只需讀取wsdl文件並弄清楚它即可。 從上面的原始XML中可以看到,變量具有名稱空間並在需要的地方繼承,還請注意,主體位於ns1名稱空間中。

我最接近PHP的地方是使用WSDL-to-PHP轉換器,該轉換器根據文件中的函數生成大量類,但是這樣做似乎失去了所有命名空間的意義。 到目前為止,我看到的唯一使用它的方法是修改生成的類文件,如下所示:

    // some code omitted...
    use SoapVar; // added by me

    // this is declared in AddressMatchingService namespace
    class Credentials
    {

        public $AgentID = null;
        public $Username = null;
        public $Password = null;

        public function __construct($AgentID, $Username, $Password)
        {
          //$this->AgentID = $AgentID;
          $this->AgentID = new SoapVar($AgentID, null, null, null, null, "http://webservices.company.co.uk/ServiceBase/");

          //$this->Username = $Username;
          $this->Username = new SoapVar($Username, null, null, null, null, "http://webservices.company.co.uk/ServiceBase/");

          //$this->Password = $Password;
          $this->Password = new SoapVar($Password, null, null, null, null, "http://webservices.company.co.uk/ServiceBase/");
        }
    }



    $wsdl = base_path() . '/resources/wsdl/AddressMatchingService.wsdl';
    $soap = new SoapClient($wsdl, array('trace'=>1));

    $creds = new AddressMatchingService\Credentials('123', 'user@company.com','PASSword');
    $address = new AddressMatchingService\Address('NG42DJ');

    $request = array('request' => $request);
    $request = new SoapVar($request, SOAP_ENC_OBJECT);

    $response = $soap->__soapCall("GetAvailableAddresses", array('request' => $request));

這讓我很接近:

    <?xml version="1.0" encoding="UTF-8"?>
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://webservices.company.co.uk/ServiceBase/" xmlns:ns2="http://webservices.company.co.uk/AddressMatching">
    <SOAP-ENV:Body>
        <ns2:GetAvailableAddresses>
            <request>
                <Address>
                    <PostCode>NG42DJ</PostCode>
                </Address>
                <ns1:UserCredentials>
                    <ns1:AgentID>123</ns1:AgentID>
                    <ns1:Password>PASSword</ns1:Password>
                    <ns1:Username>user@company.co.uk</ns1:Username>
                </ns1:UserCredentials>
                <UPRN/>
            </request>
        </ns2:GetAvailableAddresses>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

但是,如果在Python中如此簡單,我想我可能做錯了什么。 在每個類中指定名稱空間似乎很痛苦,而且我仍然不知道是否有可能將Body的名稱空間從'SOAP-ENV'更改為ns1。 如果可以避免的話,我想避免手工制作XML,因為WSDL中有許多函數和變量,所以我理想地希望使其像Python suds庫一樣高效地工作!

SOAP-ENVns1不是名稱空間,而是它們的別名。 實際的名稱空間是xmlns:*屬性中的值。 在您的第一個示例中,它們將解析為相同的名稱空間。

  • SOAP-ENV:Envelope -> {http://schemas.xmlsoap.org/soap/envelope/}Envelope SOAP-ENV:Envelope
  • SOAP-ENV:Header -> {http://schemas.xmlsoap.org/soap/envelope/}Header SOAP-ENV:Header
  • ns1:Body -> {http://schemas.xmlsoap.org/soap/envelope/}Body

別名不會改變含義。 對於同一個名稱空間使用不同的別名可能會被認為是不好的,因為它會降低可讀性。

其次,僅因為默認API僅具有一些帶有許多特定參數的調用,並不意味着您必須直接使用它們。 考慮使用輔助方法或循環以避免重復自己:

class Credentials
{
    private namespaceUri = "http://webservices.company.co.uk/ServiceBase/";

    public $AgentID = null;
    public $Username = null;
    public $Password = null;

    public function __construct($AgentID, $Username, $Password)
    {
      $this->AgentID = $this->createSoapValue($AgentID);
      $this->Username = $this->createSoapValue($Username);
      $this->Password = $this->createSoapValue($Password);
    }

    private function createSoapValue($value) {
      return new new SoapVar($value, null, null, null, null, $this->namespaceUri);
    }
}

最后檢查request元素。 我認為您忘記了它的名稱空間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM