toxml failes with "Instance of type ... has no bound element for start tag

Help
2013-11-11
2013-12-17
  • Harold Solbrig
    Harold Solbrig
    2013-11-11

     
  • Harold Solbrig
    Harold Solbrig
    2013-11-11

    We frequently inherit from pyxb generated classes. (See attached file for example). This fails in the latest 1.2.3 with a start tag error. One way this can be fixed is, in the toDOM method in basis.py, insert the following lines:

        if bds is None:
            bds = domutils.BindingDOMSupport()
        need_xsi_type = bds.requireXSIType()
        if isinstance(element_name, (str, unicode)):
            element_name = pyxb.namespace.ExpandedName(bds.defaultNamespace(), element_name)
        if (element_name is None) and (self._element() is not None):
            element_binding = self._element()
            element_name = element_binding.name()
            need_xsi_type = need_xsi_type or element_binding.typeDefinition()._RequireXSIType(type(self))
        # INSERT HERE
        if element_name is None:
            element_name = self._ExpandedName
        # END INSERT
        if element_name is None:
            raise pyxb.UnboundElementError(self)
    

    these two lines were removed from the 1.2.2 basis.py and replaced with the exception above.

     
    Last edit: Harold Solbrig 2013-11-11
  • Peter A. Bigot
    Peter A. Bigot
    2013-11-11

    The former behavior, and that resulting from your patch, is trac#203. That PyXB ever allowed a type to automatically become an element tag was an error.

    You need to augment your schema so there is an element named Foo that has type Foo.

    Also see more extended discussion here which provides an alternative solution where the desired element is explicitly associated with the binding instance.

     
  • Peter A. Bigot
    Peter A. Bigot
    2013-11-11

    In the context of extending classes, it may be that you're missing the call to _SetSupersedingClass() which is supposed to ensure that bound elements are created using the extended class rather than the base class automatically associated with the element in the generated bindings. See also this page.

     
  • Peter A. Bigot
    Peter A. Bigot
    2013-11-11

    Here's an annotated and updated version of your example that does what I think you want:

    # -*- coding: utf-8 -*-
    import logging
    if __name__ == '__main__':
        logging.basicConfig()
    _log = logging.getLogger(__name__)
    import pyxb.binding.generate
    import pyxb.binding.datatypes as xs
    import pyxb.binding.basis
    import pyxb.utils.domutils
    
    import os.path
    xsd='''<?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:complexType name="Foo">
            <xs:sequence>
               <xs:element name="entry" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        <!-- NEW element -->
        <xs:element name="Foo" type="Foo"/>
    </xs:schema>'''
    code = pyxb.binding.generate.GeneratePython(schema_text=xsd)
    
    rv = compile(code, 'test', 'exec')
    eval(rv)
    
    from pyxb.exceptions_ import *
    
    import unittest
    
    # Note name clash resolved by renaming type, not element
    class FooWrapper(Foo_):
        # No need to override constructor.
    
        # Add functionality to extension
        def lcentry (self):
            return self.entry.lower()
    # Ensure creation of element Foo() instantiates the wrapping class
    Foo_._SetSupersedingClass(FooWrapper)
    
    class Test_simple (unittest.TestCase):
        def test (self):
          x = Foo() # Create through element, not underlying type
          x.entry = "Something"
          self.assertEqual( x.toxml(), '''<?xml version="1.0" ?><Foo><entry>Something</entry></Foo>''')
          # Verify that bound element is instance of the extended class
          self.assertTrue(isinstance(x, FooWrapper))
          self.assertEqual('something', x.lcentry())
    
    if __name__ == '__main__':
        unittest.main()
    
     
  • Harold Solbrig
    Harold Solbrig
    2013-12-17

    Thanks! I hadn't realized how the Superseding Class worked -- this is useful.