specify attributes on a nil xml element

1.7k Views Asked by At

This is a long one...

I have an xsd, which specifies a complex type that can have a nillable element, but that element has a required attribute. Here is a simplified example:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" >
    <xs:element name="Test">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="NillableElementTest" type="MyNillableElement" nillable="true" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="MyNillableElement">
        <xs:sequence>
            <xs:element name="id" minOccurs="1" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="RequredAttribute" use="required"/>
    </xs:complexType>
</xs:schema>

Based on the above schema, the following xml documents are valid:

<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <NillableElementTest RequredAttribute="test" xsi:nil="true"></NillableElementTest>
</Test>

<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</Test>

It would be invalid to have a NillableElementTest element with no RequredAttribute value:

<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <NillableElementTest xsi:nil="true"></NillableElementTest>
</Test>

I have an object model (classes) that represents the above schema. The object model was generated from the xsd by the .net framework tool.

If I deserialize the xml to an object instance, the NillableTestElement property is always null as long as the xml specified xsi:nil="true". Normally this would make sense to me, except for the fact that the NillableTestElement property will not represent the RequredAttribute value that was specified in the xml.

The xml schema primer states that the nil mechanism applies only to element values, and not to attribute values. An element with xsi:nil="true" may not have any element content but it may still carry attributes.

The scenario where an element is nil but attributes aren't doesn't seem to be able to be represented by the generated object model.

So now if I take the object instance and try to serialize it to xml, I will get invalid xml if it is validated against the schema, because the object serializes the MyNillableElement as:

<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <NillableElementTest xsi:nil="true"></NillableElementTest>
</Test>

...and clearly the xsd states that the NillableELementTest element must have a RequredAttribute attribute.

Here's my questions:

So how (or is it possible) to specify that the element is null but also specify the attribute value in the object so it serializes properly?

2

There are 2 best solutions below

4
On

You said it best in your question:

The scenario where an element is nil but attributes aren't doesn't seem to be able to be represented by the generated object model.

In C#, the sub-element NillableElementTest is represented as a reference to another object. If the element is nil-valued, it is interpreted as a null reference, which, as you know, can't possibly carry values for other attributes.

In XML, as you've shown, it is possible to have an element which is nil-valued but still carry other attributes. This paradigm doesn't transfer well to objects.

Would it work for you to allow your MyNillableElement to contain 0 or more instances of id, rather than at least 1? This way, you allow yourself the possibility of having an empty one, which is able to carry the other attributes, rather than having null/nil.

0
On

I had a similar problem. Maybe my solution will not solve the problem in all cases, but I hope it will help someone.

My solution was to modify the XmlElement attribute of the NillableElementTest property in the object model. I had the attribute [XmlElement(IsNullable = true)] for the property. After I changed the attribute to [XmlElement], the property was not added to the generated xml anymore, when the value of the property was null.

The generated xml based on the schema was still valid (minOccurs="0").