Question

I've not found a way to describe an xml attribute for a repeatable primitive type; my best guess so far:

class Contact(ComplexModel):
    "contact person and communication channel"
    contactName = primitive.Unicode(min_len=1, max_len=70, nillable=False)
    channel = primitive.Unicode(max_occurs='unbounded')
    channelCode = XmlAttribute(Enum('TELEPHONE', 'TELEFAX', 'EMAIL', 'WEBSITE', type_name='channelCode'), attribute_of='channel')

This produces a wsdl that looks like correct (at least to me):

<xs:complexType name="Contact">
    <xs:sequence>
        <xs:element name="channel" minOccurs="0" maxOccurs="unbounded" nillable="true">
            <xs:complexType>
                <xs:simpleContent>
                    <xs:extension base="xs:string">
                        <xs:attribute name="channelCode" type="tns:channelCode"/>
                    </xs:extension>
                </xs:simpleContent>
            </xs:complexType>
        </xs:element>
        <xs:element name="contactName" type="tns:Contact_contactNameType" minOccurs="0"/>
    </xs:sequence>
</xs:complexType>

But I don't know how to use the Contact class!

>>> c = Contact()
>>> c.contactName = 'xxx'
>>> c.channel = [ '1', '2' ]
>>> # c.channelCode = ???
Was it helpful?

Solution

You're almost there :) You just need to put type declaration for channelCode to a separate variable.

ChannelCodeType = Enum('TELEPHONE', 'TELEFAX', 'EMAIL', 'WEBSITE',
                                               type_name='channelCode')

class Contact(ComplexModel):
    "contact person and communication channel"
    contactName = primitive.Unicode(min_len=1, max_len=70, nillable=False)
    channel = primitive.Unicode(max_occurs='unbounded')
    channelCode = XmlAttribute(ChannelCodeType, attribute_of='channel')

Now you can do proper assignments:

>>> c = Contact()
>>> c.contactName = 'xxx'
>>> c.channel = [ '1', '2' ]
>>> c.channelCode = [ChannelCodeType.TELEPHONE, ChannelCodeType.FAX]

Or just:

>>> Contact(
...     contactName='xxx',
...     channel=[ '1', '2' ],
...     channelCode=[ChannelCodeType.TELEPHONE, ChannelCodeType.FAX]
... )

Also, while I'm not in the "tests are part of documentation" camp, I thought it'd be approriate to put a link to the relevant test as this is directly related to your use case.

https://github.com/arskom/spyne/blob/1d5ecf26da1d29b68d92451ebf33e5db3f8833dc/spyne/test/protocol/test_xml.py#L141

Last bit: attribute_of will be deprecated as of 2.11. It won't be removed for the 2.x series but it'll go away in 3.x. XmlData will replace it, which is both easier to implement and faster. Details will be in the 2.11 docs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top