Search code examples
xmlxsdschema

XSD syntax for declaring element that cannot have a child element or other content


Would this be the proper method of declaring an XML element Foo that cannot have a child element or other content?

<xs:element name="Foo" type="xs:string" fixed="" nillable="true" />

The valid examples of this element in an XML document would be:

<Foo></Foo>

and

<Foo/>

Anything else would be invalid, e.g.:

<Foo>stuff</Foo>

It would be nice, though not essential, that the following be valid

<Foo>
</Foo>

Solution

  • I combined a few options into a single schema and attempted to use it to validate some test elements.

    Sources: http://www.w3schools.com/schema/schema_complex_empty.asp

    http://www.herongyang.com/XML-Schema/complexType-Empty-Element-Declaration.html

    The schema:

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="root">
        <xs:complexType>
          <xs:choice maxOccurs="unbounded">
            <xs:element name="foo">
              <xs:complexType></xs:complexType>
            </xs:element>
            <xs:element name="y1">
              <xs:simpleType>
                <xs:restriction base="xs:string">
                  <xs:length value="0" />
                </xs:restriction>
              </xs:simpleType>
            </xs:element>
            <xs:element name="y2">
              <xs:complexType>
                <xs:complexContent>
                  <xs:restriction base="xs:anyType" />
                </xs:complexContent>
              </xs:complexType>
            </xs:element>
          </xs:choice>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    Test cases:

    <?xml version="1.0" encoding="UTF-8"?>
    <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="NewXMLSchema.xsd">
     <!--  These six are all valid -->
      <foo />
      <y1 />
      <y2 />
      <foo></foo>
      <y1></y1>
      <y2></y2>
      <!-- These three are all invalid! -->
      <foo>
      </foo>
      <y1>
      </y1>
      <y2>
      </y2>
      <!--  These are invalid too. -->
      <foo>invalid</foo>
      <y1>invalid</y1>
      <y2>invalid</y2>
    </root>
    

    It looks like any of the three element declarations would do what you want, except for the extra blank line feature.

    I wouldn't include type="xs:string", fixed="", or nillable="true" because these are all semantically different from an empty tag. An empty tag wouldn't really have a type (like string) because it's empty. It also wouldn't have a fixed value of the null string, because that's different from being empty. A nillable element is semantically different from an empty tag because it is a semantically equivalent to the tag being absent (Source: XSLT 2.0 and XSLT 2.0 Programmer's Reference by Michael Kay, p. 182.). An empty tag like <br/> does not mean that, in this case, the line break is absent. It means that the line break is present but has no content or attriubtes.