2

I have an XSD element

<xsd:element name="author" type="cmd:Author" nillable="true">
    <xsd:annotation>
        <xsd:documentation>Contains author name and author id
        </xsd:documentation>
    </xsd:annotation>
</xsd:element>

Type author:

<xsd:complexType name="Author">
    <xsd:annotation>
        <xsd:documentation>Author's name and id.
        </xsd:documentation>
    </xsd:annotation>
    <xsd:simpleContent>
        <xsd:extension base="cmd:AuthorName">
             <xsd:attribute name="id" type="cmd:Id" use="optional">
                <xsd:annotation>
                    <xsd:documentation>Author's Id
                    </xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
        </xsd:extension>
    </xsd:simpleContent>
</xsd:complexType>

Base AuthorName:

<xsd:simpleType name="AuthorName">
    <xsd:annotation>
        <xsd:documentation>Type defining author's name. 
                It may contain characters from AllowedChars
        </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="cmd:AllowedChars">
        <xsd:maxLength value="112"/>
    </xsd:restriction>
</xsd:simpleType>

Type Id:

<xsd:simpleType name="Id">
    <xsd:annotation>
        <xsd:documentation>Id
        </xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
        <xsd:pattern value="\d{6}"/>
    </xsd:restriction>
</xsd:simpleType>

The problem is that I always have an ID but sometimes it may happen that AuthorName is null.

In that situation what I get is:

<author id="111111"/>

What I want to get is:

<author id="111111" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:nil="true"/>

My actual state makes problems with schema compatibility. Is it possible to do the thing I want without changing XSD model? Splitting Author into AuthorName and AuthorId isn't backward compatible and will require rewriting pretty big application.

Additional info (I'm not quite sure what is useful and what isn't): application is in J2E, I'm binding xsd with JAXB and I am generating classes using XJC.

Generated class Author:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Author", propOrder = {
    "value"
})
public class Author implements Serializable
{
    @XmlValue
    protected String value;
    @XmlAttribute(name = "id")
    protected String id;
    //getters and setters
}
garlicsauce
  • 53
  • 2
  • 10

1 Answers1

1

You may need to provide more information regarding the implementation as well; most likely, that is what constrains you from getting what you need.

Spec wise, you're correct. The XSD spec is clear when stating that other XML attributes may appear in an element whose xsi:nil attribute has been set to true (the emphasis is mine).

An element may be ·valid· without content if it has the attribute xsi:nil with the value true. An element so labeled must be empty, but can carry attributes if permitted by the corresponding complex type.

The problem is that most binding technologies have not implemented this behaviour. For e.g., this article on MSDN clearly indicates your scenario as not supported by their standard XML serializer. This is an excerpt:

  • When deserializing an XML document into objects: If the XmlSerializer class encounters an XML element that specifies xsi:nil="true", it assigns a null reference to the corresponding object and ignores any other attributes. This situation can arise if the XML document has been created by an XML Schema implementation that allows other attributes to appear along with xsi:nil="true"—effectively not binding a nil value of true to a null object reference.

Conversely, it'll not be able to work the other way around, i.e. if any other attribute is set, it'll not be able to serialize an xsi:nil="true" attribute.

If you're doing this in house, there might be ways to adjust serializers to work the way you want - again, you need to provide more info. Otherwise, you should assume, as I've shown above, that there are platforms for which this is simply not going to work (out of the box).

Petru Gardea
  • 21,373
  • 2
  • 50
  • 62