[英]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-ENV
或ns1
不是名稱空間,而是它們的別名。 實際的名稱空間是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.