我正在使用zeep(Python 3.6)与SOAP API进行接口,并使用包含本节的WSDL模式:

<xs:element name="passengers">
    <xs:complexType>
        <xs:sequence>
            <xs:element maxOccurs="unbounded" name="passenger" type="com:PassengerType"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>


所以我希望我的zeep生成的XML看起来像这样:

<book:passengers>
    <book:passenger>
        ...redacted...
    </book:passenger>
</book:passengers>


我使用Zeep达到此目标的第一次尝试是这样的:

passengers = [factories.PassengerType()]


但是,将其发送到我的SOAP API时,会产生以下错误:

File "/usr/local/lib/python3.6/site-packages/zeep/xsd/elements/element.py", line 220, in validate
  "Missing element %s" % (self.name), path=render_path)
zeep.exceptions.ValidationError: Missing element passenger (createBookingRecordRequest.passengers)


我相信这是因为我的'passengers'属性应包含标记名称为“ passenger”的Zeep对象,其中将包含我的元素列表。我已经尝试过修改zeep.xsd.AnyType来实现此目的,但尚未成功。

任何建议,将不胜感激。

最佳答案

现在,我已经回答了自己的问题,但没有收到其他任何答案。

这个问题的根源在于,我试图创建XML元素,而SOAP API的WSDL没有将XML元素明确定义为一种类型。不过这没关系,因为Zeep仍将为其生成类型对象,因此它不会将这些类型分配给特定名称,因此我们必须跳过一些额外的步骤才能获得这些类型。这是我花了一些时间才弄清楚的。

您可以通过任何父类型访问它们来获取这些对象。它们以2元组的列表形式存储在名为elements的属性中。在这种情况下,我的PassengerType对象应该由属性名称为“ passengers”的序列容器包含。例如,如果我的父类型名为ParentType,则可以这样使用“乘客”序列:

passengers = dict(ParentType.elements)['passengers'](
    PassengerType(),
    ...
    PassengerType()
)


在这里,我们将elements对象转换为dict(利用了一个2元组的列表,其中第一项是属性名称的字符串),然后按名称将元素拉出。

结果对象可以直接传递到ParentType中,例如:

ParentType(passengers=passengers)


简单。

我发现的另一种选择是使用zeep的xsd对象显式构建类型。示例如下所示。

from lxml import etree
from zeep import xsd

PassengersType = xsd.ComplexType(
    xsd.Sequence([
        xsd.Element('passengers', PassengerType, min_occurs=1, max_occurs='unbounded')
    ]), qname=etree.QName("{http://example.com/schema}passengers")
)


我认为这不是很好,但是对于在此登陆的人可能有用。

关于python - 使用zeep/python创建XML序列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44658401/

10-09 05:59