xsi:type not managed properly when base type is not abstract #32

Closed
marojor opened this Issue Apr 20, 2015 · 1 comment

Projects

None yet

2 participants

@marojor
marojor commented Apr 20, 2015

Consider the following schema (customer.xsd):

<?xml version="1.0" encoding="UTF-8"?>
<schema 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org/customer" 
    xmlns:tns="http://www.example.org/customer" 
    elementFormDefault="qualified">

    <element name="customer">
        <complexType>
            <sequence>
                <element name="address" type="tns:address"/>
            </sequence>
        </complexType>
    </element>

    <complexType name="address">
        <sequence>
            <element name="street" type="string"/>
        </sequence>
    </complexType>

    <complexType name="canadianAddress">
        <complexContent>
            <extension base="tns:address">
                <sequence>
                    <element name="postalCode" type="string"/>
                </sequence>
            </extension>
        </complexContent>
    </complexType>

</schema>

It defines an type address and a derived type canadianAddress.

A valid XML document reads as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer xmlns="http://www.example.org/customer">
    <address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="canadianAddress">
        <street>1 A Street</street>
        <postalCode>Ontario</postalCode>
    </address>
</customer>

Generating the bindings with PyXB 1.2.4:

python /tmp/PyXB-1.2.4/scripts/pyxbgen -u customer.xsd -m customer

PyXB is able to read the XML properly, but fails to encode it back to XML (attribute "xsi:type") is missing:

>>> import customer
>>> x = customer.CreateFromDocument(open("customer.xml").read())
>>> x.address
<customer.canadianAddress object at 0x16ccdd0>
>>> print x.toxml()
<?xml version="1.0" ?>
<ns1:customer xmlns:ns1="http://www.example.org/customer"><ns1:address><ns1:street>1 A Street</ns1:street><ns1:postalCode>Ontario</ns1:postalCode></ns1:address></ns1:customer>

Looking at the code I can see that a class must be abstract to require xsi:type attribute, but to my knowledge a non-abstract type could require it as well:

 325     @classmethod
 326     def _RequireXSIType (cls, value_type):
 327         if cls._IsUrType():
 328             # Require xsi:type if value refines xs:anyType
 329             return value_type != cls
 330         return cls._Abstract and value_type != cls._SupersedingClass()

I tried removing the abstract condition, but then the code fails for xsd:union types.

@pabigot pabigot added a commit that closed this issue Apr 20, 2015
@pabigot fix #32: xsi:type missing on extended/restricted element content
All past experience with xsi:type had been with cases where the element
was declared as having an abstract type.  It's also permissible to
extend or refine the type that's expected by the schema.  When that's
happened, make sure the XML that's generated from the binding preserves
the fact-of the extension/restriction by specifying the corresponding
type.
7d4e557
@pabigot pabigot closed this in 7d4e557 Apr 20, 2015
@pabigot
Owner
pabigot commented Apr 20, 2015

Thanks for the report; I agree that xsi:type should be maintained when extending/restricting a non-abstract class. Try applying the patch that's now in the next branch.

@pabigot pabigot added a commit that referenced this issue Apr 25, 2015
@pabigot binding/basis: restore part of xsi:type behavior
The fix for issue #32 uses xsi:type unconditionally on abstract types, a
change from the previous behavior that did so only when the value type
didn't match a superseding class associated with the abstract type.
Instead of attempting to create a situation that distinguishes the
conditions revert to how that case has been handled for the past five
years.
8ed24b0
@pabigot pabigot added this to the PyXB 1.2.5 milestone Sep 18, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment