random technical thoughts from the Nominet technical team

Why no substitutionGroup for attributes in XML Schema?

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted by jay on Mar 9th, 2006

There is a feature of XML Schema called substitutionGroup that is a very neat way to extend schemas. Unfortunately this only applies to elements, not attributes. But before I get to that, here’s a basic explanation of substitutionGroup.

substitutionGroup for elements

In the following example I’ve defined an element <command> based on the type “commandType”. That type in turn is a sequence that so far contains just one element, which is an <abstractCommand>. <abstractCommand> in turn is of the type “abstractExtensionType”, which is defined as an empty type.

<!-- extract from schema1.xsd -->

<element name="command" type="schema1:commandType"/>

<complexType name="commandType">
<element ref="schema1:abstractCommand" />

<element name="abstractCommand"
type="schema1:abstractCommandType" />

<complexType name="abstractCommandType" />

Now none of that is actually usable at the moment because the <abstractCommand> element doesn’t actually contain anything useful. So all we can do is this following pointless code:

<!-- extract from document1.xml -->

However let’s assume this is part of a much larger document, in which case we use this as a place marker. Then we create our second schema, where we provide a concrete command. In this case we define a new element called “create”, which can be used in place of <schema1:abstractCommand> thanks to the substitutionGroup attribute. This is also based on a type that is derived from the type of the element that it is used in place of. In other words <create> is of the type “schema2:extCommandType”, which in turn is an extension of “schema1:abstractCommandType”.

<!-- extract from schema2.xsd -->
<element name="create" substitutionGroup="schema1:abstractCommand"
type="schema2:extCommandType" />

<complexType name="extCommandType">
<extension base="schema1:abstractCommandType">
<any namespace="##other" maxOccurs="unbounded"/>

So, to finish off the explanation, we can now use all of this in a new document that uses the <schema1:command> element from the first file, but contains the “create” command specified in the second file.

<!-- extract from document2.xml -->

The final point is that if we had wanted to prevent anyone from create an <abstractCommand> element , just to be tidy, then we could have defined it using the “abstract” attribute:

<complexType name="abstractCommandType" abstract="true" />

substitutionGroup for attributes

XML Schema does not actually support substitutionGroup for attributes, but if it did then what would it look like? Well a bit like this:

<!-- extract from schema1.xsd -->

<complexType name="operation">
<any namespace="##other" />
<attribute ref="schema1:opcode" use="required" />

<attribute name="opcode" type="schema1:opcodeType" />

<simpleType name="opcodeType">
<restriction base="token">
<enumeration value="request">
<enumeration value="approve">
<enumeration value="reject">
<enumeration value="withdraw">

<!-- extract from schema2.xsd -->

<simpleType name="extendedOpcodeType">
<union memberTypes="schema1:opcodeType">
<restriction base="token">
<enumeration value="dispute">

<attribute name="extendedOpcode" type="schema2:extendedOpcodeType"
substitutionGroup="schema1:opcode" />

<!-- extract from document1.xml -->

<operation extendedOpcode="dispute">
<blah />

I’ve proposed this to the XML Schema working group to see if they might consider it for v1.1

Further reading

If you are interested in reading more about XML Schema or substitutionGroup then don’t bother looking these up in the XML Nutshell book as these only get a cursory section. Use a specialist XML Schema book instead.

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.

Recent Posts

Highest Rated