spyne

get_object_as_xml not working with polymorphism


I would like to export object as xml string with spyne. It works well using function named 'get_object_as_xml' but it does not take polymorphism into account as you can see in the following example. I have tried to add the line: xml_object.polymorphic = True without success.

simple code:

from spyne.util.xml import xml_object
from spyne.model.complex import ComplexModel
from spyne.model.primitive import Unicode
from spyne.util.xml import get_object_as_xml, get_xml_as_object
from xml.dom.minidom import parseString
from xml.etree.ElementTree import tostring, fromstring

class B(ComplexModel):
    _type_info = {
        '_b': Unicode,
    }

    def __init__(self):
        super().__init__()
        self._b = "b"


class C(B):
    _type_info = {
        '_c': Unicode,
    }

    def __init__(self):
        super().__init__()
        self._c = "c"


class A(ComplexModel):
    _type_info = {
        '_a': Unicode,
        '_b': B,
    }

    def __init__(self, b=None):
        super().__init__()
        self._a = 'a'
        self._b = b


a = A(C())
# xml_object.polymorphic = True
element_tree = get_object_as_xml(a, A)
xml_string = parseString(tostring(element_tree, encoding='utf-8', method='xml')).toprettyxml(indent="    ")
print(xml_string)

result without xml_object.polymorphic = True:

<?xml version="1.0" ?>
<A>
    <_a>a</_a>
    <_b>
        <_b>b</_b>
    </_b>
</A>

result with xml_object.polymorphic = True:

AppData\Local\Continuum\anaconda3\envs\presto_env\lib\site-packages\spyne\protocol\xml.py", line 722, in gen_members_parent
    attrib[XSI_TYPE] = cls.get_type_name_ns(self.app.interface)
AttributeError: 'NoneType' object has no attribute 'interface'

Process finished with exit code 1

I am using version 2.13.2a0 of spyne. Does this feature is supported or I am doing something wrong ?

Cheers,


Solution

  • get_object_as_xml_polymorphic landed with PR #619 You can use it now or wait for next release in the coming weeks.

    Here's how it's supposed to work:

    #!/usr/bin/env python
    
    from __future__ import print_function
    
    import sys
    
    from lxml import etree
    from spyne.util import six
    
    from spyne import ComplexModel, Unicode
    from spyne.util.xml import get_object_as_xml_polymorphic
    
    
    class B(ComplexModel):
        _type_info = [
            ('_b', Unicode(default="b")),
        ]
    
    
    class C(B):
        _type_info = [
            ('_c', Unicode(default="c")),
        ]
    
    
    class A(ComplexModel):
        _type_info = [
            ('a', Unicode(subname="_a")),
            ('b', B.customize(subname="_b")),
        ]
    
    
    a = A(b=C())
    elt = get_object_as_xml_polymorphic(a, A, no_namespace=True)
    xml_string = etree.tostring(elt, pretty_print=True)
    if six.PY2:
        print(xml_string, end="")
    else:
        sys.stdout.buffer.write(xml_string)
    

    output:

    <A>
      <b xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="C">
        <_b>b</_b>
        <_c>c</_c>
      </b>
    </A>