2012-04-18 31 views
5

मैं क्लाइंट को लागू करने के लिए पायथन/सूड का उपयोग करता हूं और मुझे wsdl में element ref= द्वारा परिभाषित पैरामीटर के नमूने प्रकार के लिए भेजे गए 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-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= द्वारा परिभाषित सभी तर्कों के लिए होता है। यह स्वचालित रूप से कैसे ठीक किया जा सकता है?

नोट: मैंने जांच की है कि "अच्छा" उपसर्ग सेवा द्वारा मैन्युअल एसओएपी अनुरोध मैन्युअल रूप से कर्ल के माध्यम से भेजकर स्वीकार किया जाता है।

अद्यतन

मैं साबुन का झाग स्रोत कोड के साथ meddled और ref= विशेषता के साथ सभी तत्वों को निम्नलिखित अनुभवजन्य ठीक बलों रेफरी एड नाम स्थान ग्रहण करने के लिए (पहले, वे स्कीमा जड़ नाम स्थान पर ले या जो कुछ भी 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 

काम करता है, लेकिन मुझे यकीन है कि अगर यह दूसरी बात निकाल लेंगे नहीं कर रहा हूँ रों। मैं एक बेहतर समाधान पसंद करूंगा जो एसयूडीएस स्रोत कोड नहीं बदलेगा।

धन्यवाद,

एलेक्स

+0

पसंद करते हैं यह स्पष्ट रूप से अपने ढेर में एक बग है; "स्वचालित रूप से" से आपका क्या मतलब है? उदाहरण के लिए, क्या आप एक अलग, लेकिन समकक्ष एक्सएसडी के साथ काम करने के इच्छुक हैं जो आपके टूलींग के साथ काम करेगा? आप जो कहते हैं उससे, यदि आप स्थानीय रूप से परिभाषित तत्व के साथ रेफरी को प्रतिस्थापित करेंगे, तो यह काम करेगा; सभी एक्सएसडी परवाह करने के लिए, जेनरेट एक्सएमएल वही होगा। यदि आप उड़ान पर बदलने के बारे में सोचते हैं, जैसे किसी प्रॉक्सी के माध्यम से एक्सएसएलटी के किसी प्रकार का उपयोग करना, यह एक अलग दृष्टिकोण होगा। मैं ऐसे समाधान की अनुशंसा कर सकता हूं जो स्थानीय तत्वों के साथ रेफरी को प्रतिस्थापित करने के लिए स्वचालित रूप से आपके एक्सएसडी को दोबारा कर देगा। –

+0

मैंने वास्तव में परिभाषाओं को बदलने और बदलने की कोशिश की, लेकिन चूंकि मैं एक विशेषज्ञ नहीं हूं, इसलिए मैंने सही वाक्यविन्यास को इंगित नहीं किया है, एसयूडीएस ने गलत नामस्थान रखा है। मैं इनके साथ नहीं रहना पसंद करूंगा, क्योंकि वे बाहरी विक्रेता द्वारा प्रदान किए जाते हैं और परिवर्तनों के अधीन होते हैं। अब तक मिले एक गैर-इष्टतम समाधान के लिए अद्यतन देखें। –

उत्तर

8

लिखें Suds plugin एक्सएमएल संशोधित करने के लिए यह भेजे जाने से पहले।

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

यह इस विशिष्ट मामले के लिए ठीक काम करेगा। हालांकि, विभिन्न पेड़ की स्थिति में ऐसे कई पैरामीटर हैं, इसलिए हाथ से उन्हें ठीक करना इष्टतम नहीं है। मुझे ref = _ के साथ सभी तत्वों के लिए _prefix ns0 जैसे कुछ चाहिए, और जब कोई तर्कसंगत रूप से पूरे एक्सएमएल पेड़ को पार्स कर सकता है, तो मुझे लगता है संदर्भ। लिफाफा 'ref = 'जानकारी को बरकरार नहीं रखता है। –

+0

एक और विकल्प डब्लूएसडीएल/एक्सएसडी ऑब्जेक्ट को संशोधित करने के लिए 'DocumentPlugin' को विस्तारित कर रहा है, 'पार्सेड()' विधि (दस्तावेज़ देखें) को दो बार बुलाया जाएगा (डब्लूएसडीएल के लिए एक, एक्सएसडी के लिए दूसरा)। – dusan

+0

शानदार, धन्यवाद !! दिलचस्प बात यह है कि मुझे लिफाफे को सटीक उसी स्थान पर (संरचनात्मक रूप से) प्रारंभिक उदाहरण के रूप में सही करना था। क्या यहां कोई पैटर्न है? – Gesias

1

आप साबुन संदेश अपने आप का निर्माण और SoapClient का उपयोग संदेश भेजने के लिए कर सकते हैं:

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

मैं जब झाग एक BizTalk/आईआईएस सोप सेवा का उपयोग करने का उपयोग कर ठीक उसी समस्या थी। डब्लूएसडीएल से मैं जो कह सकता हूं उससे यह तब होता है जब "कॉम्प्लेक्स टाइप" होता है जो "लक्ष्य नामस्थान" का हिस्सा नहीं है (यह स्वयं का है), जिसमें एक बच्चा है जो जटिल कॉम्प्लेक्स भी है, लेकिन बिना नामस्थान सेट के। बिज़टॉक में इसका मतलब है कि बच्चे को समान नामस्थान के माता-पिता के रूप में होना चाहिए, लेकिन सुड्स को लगता है कि यह लक्ष्य नामस्थान का हिस्सा होना चाहिए ....

स्रोत कोड में फिक्स ने " सही ढंग से ", लेकिन जब से मैं किसी अन्य समाधान के लिए हर बार फिक्स लगाने के बिना अपग्रेड करने में सक्षम होना चाहता हूं ....

मेरा समाधान सूड को छोड़ना था और केवल कच्चे एक्सएमएल की प्रतिलिपि बनाना था, इसे टेम्पलेट के रूप में उपयोग करना था और इसमें मूल्यों की प्रतिलिपि बनाएँ ... सुंदर नहीं, लेकिन कम से कम सरल। प्लगइन जोड़ने का समाधान मेरी राय में समान रूप से हार्डकोड किया गया है और शायद इसे बनाए रखने के लिए भी कठिन है।

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

आपकी विधि बहुत अच्छी तरह से काम नहीं करती है: WebFault: सर्वर ने गलती उठाई: 'अनुरोध के लिए मूल तत्व निर्धारित नहीं किया जा सका। – Allen

+0

mmhhh ... तो प्लगइन रणनीति रास्ता है ... –