7

クライアントを実装するために python/suds を使用していますelement ref=が、wsdl で定義された特定のタイプのパラメーターに対して、送信された SOAP ヘッダーで間違った名前空間プレフィックスを取得します。

.wsdl は、データ型の .xsd ファイルを参照しています。以下を参照してください。問題は、関数GetRecordAttributesと type の最初の引数にあり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>

suds が送信する 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>プレフィックスが間違っています 。これ は、.xsd で定義され <ns0:recordReferences>た名前空間に属しているためです。...GrantaBaseTypes

ref=これは、wsdl で定義されたすべての引数に対して発生します。これを自動的に修正するにはどうすればよいですか?

注: curl を介して xml SOAP リクエストを手動で送信することにより、「good」プレフィックスがサービスによって受け入れられることを確認しました。

アップデート

私は SUDS ソース コードをいじりました。次の経験的な修正により、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

私のサービスでは動作しますが、それが他のものを壊すかどうかはわかりません. SUDS のソース コードを変更しない、よりスマートなソリューションを希望します。

ありがとう、

アレックス

4

4 に答える 4

8

送信前に XML を変更するSuds プラグインを作成します。

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()])

Sudsのドキュメントを引用:

marshalled()
送信前にエンベロープ ドキュメントを検査/変更する機会をプラグインに提供します。

于 2012-04-19T20:37:15.017 に答える
2

suds を使用して BizTalk/IIS SOAP サービスにアクセスすると、まったく同じ問題が発生しました。WSDLからわかることから、「targetNamespace」の一部ではない「complexType」がある場合に発生します(独自のものがあります)。これには、complexTypeでもあるが名前空間が設定されていない子があります。BizTalk では、これは子が親と同じ名前空間に属している必要があることを意味しますが、Suds はそれが targetNamespace の一部であるべきだと考えているようです ....

ソースコードの修正により「正しく」解決されましたが、別の解決策に行くたびに修正を適用せずにアップグレードできるようにしたいので....

私の解決策は、Suds をスキップして生の XML をコピーし、それをテンプレートとして使用して値をコピーすることでした...美しくはありませんが、少なくとも単純です。私の意見では、プラグインを追加するソリューションはハードコード化されており、維持するのはおそらくさらに困難です。

于 2013-03-22T08:35:33.280 に答える
1

自分でsoapメッセージを作成SoapClientし、メッセージの送信に使用できます。

sc = SoapClient(cli.service.XXXMethod.client,cli.service.XXXMethod.method)
sc.send(some_soap_doc)
于 2012-06-13T07:58:59.373 に答える