2012-04-18 32 views
5

我使用python/suds來實現客戶端,並且在wsdl中由element ref=定義的參數類型的參數的發送SOAP頭中出現錯誤的名稱空間前綴。python在SOAP請求中產生錯誤的名稱空間前綴

.wsdl正在引用數據類型.xsd文件,請參見下文。問題是功能GetRecordAttributes及其類型gbt:recordReferences的第一個參數。

文件:browse2.wsdl

<xsd:schema targetNamespace="http://www.grantadesign.com/10/10/Browse" xmlns="http://www.grantadesign.com/10/10/Browse" xmlns:gbt="http://www.grantadesign.com/10/10/GrantaBaseTypes" elementFormDefault="qualified" attributeFormDefault="qualified"> 
<xsd:import schemaLocation="grantabasetypes2.xsd" namespace="http://www.grantadesign.com/10/10/GrantaBaseTypes"/> 
<xsd:element name="GetRecordAttributes"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element ref="gbt:recordReferences"> 
       </xsd:element> 

引用的文件:grantabasetypes2.xsd用肥皂水發送

<element name="recordReferences"> 
    <complexType> 
    <sequence> 
     <element name="record" minOccurs="0" maxOccurs="unbounded" type="gbt:MIRecordReference"/> 
    </sequence> 
    </complexType> 
</element> 

SOAP請求:

<SOAP-ENV:Envelope xmlns:ns0="http://www.grantadesign.com/10/10/GrantaBaseTypes" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.grantadesign.com/10/10/Browse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <SOAP-ENV:Header/> 
    <ns1:Body> 
     <ns2:GetRecordAttributes> 
     <ns2:recordReferences> 
      <ns0:record> 
      </ns0:record> 
     </ns2:recordReferences> 
     </ns2:GetRecordAttributes> 
    </ns1:Body> 
</SOAP-ENV:Envelope> 

問題<ns2:recordReferences>前綴錯誤,應爲<ns0:recordReferences>,因爲它屬於在.xsd中定義的名稱空間...GrantaBaseTypes

這發生在wsdl中由ref=定義的所有參數。這怎麼能自動修復?

注意:我通過curl手動發送xml SOAP請求來檢查服務是否接受「好」前綴。

UPDATE

我插手與SUDS源代碼和下述經驗修正力與ref=屬性的所有元件承擔REF-ED命名空間(先前,他們採取在架構根名稱空間或任何tns是) :

文件:/suds/xsd/sxbase.py

class SchemaObject(object): 
.... 
    def namespace(self, prefix=None): 

     ns = self.schema.tns 

#FIX BEGIN 
     if self.ref and self.ref in self.schema.elements.keys(): 
      ns = self.ref 
#FIX END 

作品與我的服務,但我不知道這是否會破壞其他的事情秒。我寧願選擇不改變SUDS源代碼的更智能的解決方案。

感謝,

亞歷

+0

這顯然是在棧中的錯誤; 「自動」是什麼意思?例如,您是否願意與您的工具配合使用不同但同等的XSD?從你所說的話來看,如果你想用本地定義的元素替換ref,它就可以工作;對於所有XSD關心,生成的XML將是相同的。如果你考慮改變航班,比如通過代理使用某種XSLT,那將是一種不同的方法。我可以推薦一個解決方案,它會自動重構您的XSD以替換本地元素。 – 2012-04-18 16:04:56

+0

我真的試圖移動和變化的定義,但因爲我不是專家,也許我coudn't找準正確的語法,泡沫不停地把錯誤的命名空間存在。我也不喜歡這些,因爲它們是由外部供應商提供的,並且可能會發生變化。請參閱UPDATE以獲取迄今爲止發現的非最佳解決方案。 – 2012-04-19 09:18:41

回答

8

Suds plugin修改XML在發送前。

from suds.client import Client 
from suds.plugin import MessagePlugin 

class MyPlugin(MessagePlugin): 
    def marshalled(self, context): 
     #modify this line to reliably find the "recordReferences" element 
     context.envelope[1][0][0].setPrefix('ns0') 

client = Client(WSDL_URL, plugins=[MyPlugin()]) 

報價肥皂水文檔:

整理()
提供了機會,檢查/發送之前修改信封文檔插件。

+1

對於這個特定的情況,這將工作正常。然而,由於在不同的樹位置有很多這樣的參數,所以用手修復它們並不是最佳的。我希望_prefix ns0這樣的東西適用於ref = _的所有元素,並且可以有理由地解析整個xml樹,我相信context.envelope不會保留'ref ='信息。 – 2012-04-20 08:06:18

+0

另一種選擇是延伸'DocumentPlugin'修改WSDL/XSD目的,'解析()'方法(參見文檔)將被調用兩次(一個用於WSDL,另一個用於XSD)。 – dusan 2012-04-20 17:17:05

+0

輝煌,謝謝!有趣的是,我必須在與最初的例子完全相同的地方(結構上)更正信封。這裏有模式嗎? – Gesias 2013-03-15 03:16:37

1

你可以建立自己的SOAP消息,並使用SoapClient發送消息:

sc = SoapClient(cli.service.XXXMethod.client,cli.service.XXXMethod.method) 
sc.send(some_soap_doc) 
2

我用肥皂水訪問的BizTalk/IIS SOAP服務時,有完全相同的問題。 從我可以從時,有一個「複雜類型」是不是「目標名稱」(它有它自己的),其中有一個孩子,這也是一個複雜類型的組成部分,但沒有命名空間的設置它發生的WSDL告訴。在BizTalk中,這意味着孩子應該和父母一樣屬於同一個命名空間,但是Sud似乎認爲它應該是目標命名空間的一部分......

源代碼中的修復解決了「正確的」,但因爲我希望能夠不用每次我去另一個解決方案時應用補丁升級....

我的解決辦法是跳過肥皂水和剛纔複製的原始XML,用它作爲模板,將值複製到它中...不是很美,但至少很簡單。 在我看來,添加插件的解決方案同樣是硬編碼的,可能更難以維護。

0

我喜歡的正則表達式:)

import re 

class EnvelopeFixer(MessagePlugin): 
    def sending(self, context): 
     # rimuovi i prefissi 
     context.envelope = re.sub('ns[0-9]:', '', context.envelope) 
     return context.envelope 
+0

您的方法doens't工作得很好:WebFault:服務器引發錯誤:'請求的根元素無法確定。 – Allen 2013-10-02 14:06:26

+0

mmhhh ...所以插件策略是... – 2013-10-08 08:06:09

相關問題