The first two values (restriction and extension) control any
substitution through xsi:type or substitution
groups, and block the substitution by datatypes that are derived by
restriction or extension from the datatype defined in the element
declaration. The third (substitution) is specific to the substitution
groups, and defines if an element from the substitution group (for
which the element is the head) is allowed. Since only global elements
can participate in a substitution group, the last value is clearly
meaningful for global definitions only.
The fact that the block attribute is used both for
type substitution and for substitution groups can be misleading,
especially with the values restriction and extension, which act on
both aspects. A simple example makes this more concrete.
Let's say that we have a complex type definition
(personType) describing a person as having a name,
a mandatory birth date, and optional death date and qualification:
<xs:complexType name="personType">
<xs:sequence>
<xs:element ref="name"/>
<xs:element ref="born"/>
<xs:element ref="dead" minOccurs="0"/>
<xs:element ref="qualification" minOccurs="0"/>
</xs:sequence>
<xs:attribute ref="id"/>
</xs:complexType>
We can also derive by extension from this complex type a datatype
that describes an author as a person with a list of books:
<xs:complexType name="authorType">
<xs:complexContent>
<xs:extension base="personType">
<xs:sequence>
<xs:element name="book" type="xs:token" minOccurs="1"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
We can derive by restriction a datatype that describes a character as
a person with no death date and a mandatory qualification:
<xs:complexType name="characterType">
<xs:complexContent>
<xs:restriction base="personType">
<xs:sequence>
<xs:element ref="name"/>
<xs:element ref="born"/>
<xs:element ref="qualification"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
The first purpose of block attributes in element
definitions is to control the type substitution through
xsi:type, which controls substitutions in the
instance documents such as the following (if the
person element is defined as having a type
personType):
<person xsi:type="authorType" id="CMS"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<name>
Charles M Schulz
</name>
<born>
1922-11-26
</born>
<dead>
2000-02-12
</dead>
<book>
Being a Dog Is a Full-Time Job
</book>
</person>
<person xsi:type="characterType" id="Snoopy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<name>
Snoopy
</name>
<born>
1950-10-04
</born>
<qualification>
extroverted beagle
</qualification>
</person>
TIP:
This example shows that the impact of both derivation types on the
applications is very different. A type substitution by restriction
has virtually no impact on the applications, since the content model
matching the restricted type must also match the original type.
Alternatively, a type substitution by extension allows content models
not allowed by the original type (such as the addition of the
book element in the previous example), and the
risk of breaking applications that do not expect these additions is
higher. Thus, a conservative attitude might be to include
extension in the default values of
block in your schemas.
That being said, we've seen only one side of the
block attribute. It serves a second, different,
yet not independent, purpose and also restricts the usage of
substitution groups. To illustrate this purpose,
let's define three different element members of a
substitution group whose head is person. There is
also a fourth element member, which is just a synonym for the element
person and has the same type:
<xs:element name="person" type="personType"/>
<xs:element name="author" type="authorType"
substitutionGroup="person"/>
<xs:element name="character" type="characterType"
substitutionGroup="person"/>
<xs:element name="human" type="personType"
substitutionGroup="person"/>
After defining this substitution group and without blocking anything,
we allow not only block and the type substitutions
seen above, but also element substitutions, such as:
<author id="CMS">
<name>
Charles M Schulz
</name>
<born>
1922-11-26
</born>
<dead>
2000-02-12
</dead>
<book>
Being a Dog Is a Full-Time Job
</book>
</author>
<character id="PP">
<name>
Peppermint Patty
</name>
<born>
1966-08-22
</born>
<qualification>
bold, brash and tomboyish
</qualification>
</character>
<human id="CMS.">
<name>
Charles M Schulz
</name>
<born>
1922-11-26
</born>
<dead>
2000-02-12
</dead>
</human>
The first substitution is by an element of the substitution group
whose type is derived by extension from the head. It can be blocked
by specifying a block attribute including the
value extension. The second one is a substitution
by an element of the substitution group whose type is derived by
restriction from the head. It can be blocked by specifying a
block attribute including the value
restriction. Those two are similar to the two
substitutions given as examples for the type substitutions, with the
difference that the element name is now used to differentiate the
type instead of the xsi:type attribute. The third
substitution is new, since the type is the same as the type of the
head, and it is blocked only by specifying a block
attribute that includes the value substitution.
Note that including substitution in a
block attribute blocks any element substitution,
while stating that not all the combinations are possible to express.
To block everything, you would define author as:
<xs:element name="author" type="authorType" block="#all"/>