6.

Restrictions and Substitutions

 

The restriction element comes into play while deriving new types from the base type. It merely regulates or reduces the tasks that are performed in the base type for the new type. Thus, it is imperative to first create the base type. Then, while creating the new type, the values can be curbed using the restriction element.

 

The restriction element was touched upon cursorily in the earlier chapter, but the primary focus then in that chapter was on simple types. In this chapter, we shall scrutinize the nuances of restricting the complexType element, in considerable detail.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz" type="c2" />

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="aaa" minOccurs="0" maxOccurs="unbounded" type="xs:string" />

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="aaa" minOccurs="1" maxOccurs="unbounded" type="xs:string"/>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa />

<bbb />

</zzz>

 

The root element zzz is allotted the type c2. This type starts with a complexContent element, followed by the restriction element, with its base initialized to the type c1. This lays certain restrictions on the type c1.

 

The type c1 has an element aaa with the minOccurs attribute having the value of 0. In addition, there exists a string element bbb. The type c2 has the same elements of aaa and bbb, but with the minOccurs value of 1. This ensures the presence of at least one occurrence of the element aaa in the xml file.

 

Uprooting the element aaa from the xml file would obviously flag an error.

 

Error

Element 'zzz' has invalid child element 'bbb'. Expected 'aaa'.

 

However, on eliminating aaa from the xml file and changing the type of element zzz from c2 to c1, would eliminate all errors. This is because, the element aaa becomes optional in the type c1.

 

b.xsd

...

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="aaa" minOccurs="1" maxOccurs="unbounded" type="xs:string"/>

<xs:element name="bbb" type="xs:string"/>

<xs:element name="ccc" type="xs:string"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

...

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Invalid particle derivation by restriction. An error occurred at file:///c:/xmlprg/b.xsd(9, 2).

 

The above exception is thrown because the element ccc has been added after the element bbb in complexType c2. We are not allowed to add or subtract anything from the type c1. All the original members must remain unaltered. Also, the names of the elements can neither be changed nor removed. The only permissible action is that of restricting the existing elements. However, the base type cannot be changed or extended; only the elements can be restricted.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz" type="c2" />

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="aaa" type="xs:integer" />

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="aaa">

<xs:simpleType>

<xs:restriction base="xs:integer">

<xs:maxExclusive value="100"/>

</xs:restriction>

</xs:simpleType>

</xs:element>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

<bbb />

</zzz>

 

In the above xsd program, the root element zzz is based on type c2. This type restricts type c1, which consists of two elements: element aaa, which is an integer, and element bbb, which is a string. In type c2, another element aaa is created, whose value is restricted to a maximum of 100. In this manner, the value of an element can be restricted.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz" type="c2" />

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="aaa">

<xs:simpleType>

<xs:restriction base="xs:integer">

<xs:maxExclusive value="100"/>

</xs:restriction>

</xs:simpleType>

</xs:element>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c3">

<xs:sequence>

<xs:element name="aaa">

<xs:simpleType>

<xs:restriction base="xs:integer">

<xs:maxExclusive value="100"/>

</xs:restriction>

</xs:simpleType>

</xs:element>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

<xs:complexType name="c3">

<xs:sequence>

<xs:element name="aaa" type="xs:integer" />

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

<bbb />

</zzz>

 

In the above example, the root element zzz is assigned the type c2. This complexType c2 contains the complexContent. Then, using the restriction element, it restricts its type to c3. This type c3 is very elementary. It has an integer element aaa and a string element bbb. In type c3, the simpleType element is used together with restriction, to further restrict the value of the type aa to less than 100. This explains why the xml file passes validation.

 

The type c1 is created with two elements aaa and bbb. For the element aaa, a combination of simpleType and restriction has been used, wherein the restriction element regulates the integer value of the type to be less than 100. To authenticate this, change the type of zzz from c2 to c1, and you shall surely not encounter any errors.

 

Now, carry out one more minor amendment to the xsd file.

 

b.xsd

..

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="aaa">

...

 

In the complexType definition for type c2, the restriction is now based on the type c1, instead of c3. However, even though c1 is a perfectly valid type, the following exception is thrown:

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Invalid particle derivation by restriction. An error occurred at file:///c:/xmlprg/b.xsd(15, 2).

 

Thus, it is not permissible to restrict an element that has already been restricted in the parent class. Consequently, the type c1 cannot be used as a base for restriction any more.

           

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz" type="c2" />

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="aaa" minOccurs="1" maxOccurs="unbounded" type="xs:string" />

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="aaa" minOccurs="0" maxOccurs="unbounded" type="xs:string"/>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

</xs:schema>

 

The first xsd program of this chapter has been replicated here with a few modifications. The value of the minOccurs attribute in type c1 has been changed from 0 to 1, thus mandating at least one occurrence of this type in the file.

 

On similar lines, the type c2, which extends from type c1, is assigned a minOccurs value of 0. This triggers off an error, because the element has been made less restrictive, rather than being made more restrictive. The exception that is generated is the same as the one witnessed in the previous program.

 

Modify the type c1 to the following:

 

<xs:element name="aaa" minOccurs="0" maxOccurs="unbounded" type="xs:string" fixed="hi" />

 

An error erupts because the element aaa in the type c1, has been assigned a fixed value of 'hi'. Now, modify the statement in type c2 to the following:

 

<xs:element name="aaa" minOccurs="1" maxOccurs="unbounded" type="xs:string" fixed="hi1"/>

 

In the type c2, the fixed attribute is added to the element aaa, and a value of 'hi' is assigned to it. Nevertheless, this is not sufficient, since a value of 'hi' must be specified in the xml file to get rid of the error.

 

On changing the value of the fixed attribute to 'hi1', which is different from the value assigned to the element aaa, the same particle error gets reported. Thus to summarize, when we create a new type, it should be more restrictive rather than being less restrictive.

 

The Redefine element

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:redefine schemaLocation="b1.xsd">

</xs:redefine>

<xs:element name="zzz" type="c1" />

</xs:schema>

 

b1.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="aaa" type="xs:integer"/>

</xs:sequence>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

</zzz>

 

The xsd file is now assigned a new element called 'redefine'. The schemaLocation attribute is initialized to a different xsd file named b1.xsd. The file b1.xsd has a type called c1, which contains a simple element called aaa of type string. In the file b.xsd, the root element zzz is assigned the type c1.

 

No errors are visible, despite the fact that the type c1 has been created in another file. Thus, the 'redefine' element acts analogous to an 'include' or an 'import' statement. All the types that are present in the schemaLocation file can now be used in the main xsd file.

 

In the xml file, the root element zzz has a child element named aaa. The 'redefine' element works in a same manner corresponding to an 'include' or an 'import' statement, which differ from one another only with respect to the namespaces. If this is the case, then what is the necessity of having another element that behaves in a similar manner? Read on to unravel the mystery.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:redefine schemaLocation="b1.xsd">

<xs:complexType name="c1">

<xs:complexContent>

<xs:extension base="c1">

<xs:sequence>

<xs:element name="bbb" type="xs:integer"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:redefine>

<xs:element name="zzz" type="c1" />

</xs:schema>

 

b1.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="aaa" type="xs:integer"/>

</xs:sequence>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

<bbb> 10 </bbb>

</zzz>

 

This example illustrates the use of the redefine element. The 'include' or 'import' elements introduce a truck-load of types which could require some modifications to suit the requirements. This is attainable by utilizing the redefine element. Thus, the redefine element allows redefining or altering of the existing types. The above program demonstrates how this can be achieved.

 

A type called c1 is created within a complexType element, even though this type is already present in the file b1.xsd. This newly created type c1 extends from the original type c1.

 

Specifying c1 in the complexType hints at the fact that the existing definition of type c1, which is present in the file b1.xsd, needs to be changed. In the extension element, the base refers to the original c1 present in the file b1.xsd, and not to the type c1 that is being defined. Hence, no circular definition error is instigated.

 

The type c1 is extended with the help of the extension element. Thus, in addition to the existing element aaa from the original c1, another element bbb is introduced. The end-result is that the xml file can now have the two elements of aaa and bbb.  In the above program, the redefine element is used to add an element to a type, which is created in another file.

 

In file b.xsd, change the element name bbb to aaa as follows:

 

<xs:element name="aaa" type="xs:integer"/>

 

Also, change the contents in the file b.XML as follows:

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

<aaa> 20 </aaa>

</zzz>

To our amazement, no errors meet the eye. This is because, the first element aaa originates from the original type c1 based in file b1.xsd, while the second comes from the newly defined type c1, which is defined in file b.xsd. The XML framework is able to distinguish between the two identically named elements, both named aaa. But as always, there is a minor caveat.

 

In the file b.xsd, change the data type of the element aaa from integer to string as follows:

 

<xs:element name="aaa" type="xs:string"/>

 

This modification results in the following exception:

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: In the same scope elements with the same name have to have the same type. An error occurred at file:///c:/xmlprg/b.xsd(7, 2).

 

This elucidates the fact that a file can have multiple elements sharing same name, provided they have the same data type. Redefining the original aaa of type integer to the newly added element aaa of type string, leads to the above error.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:redefine schemaLocation="b1.xsd">

<xs:complexType name="c1">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="bbb" type="xs:integer"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

</xs:redefine>

<xs:element name="zzz" type="c1" />

</xs:schema>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Invalid particle derivation by restriction. An error occurred at file:///c:/xmlprg/b.xsd(3, 2).

 

In the above program, the 'extension' element is altered to 'restriction'. This generates the familiar ‘Invalid particle’ error. This exception is expected, since the basic rules of restriction have been flouted.

 

A restriction element can delimit the existing elements, but it cannot permit any additions to them. The 'redefine' element cannot alter the rules of the other elements.

 

b.xsd

...

<xs:element name="aaa" type="xs:integer"/>

...

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

</zzz>

 

In the xsd file, the element name is reverted to aaa. Further, the additional element aaa is removed from the xml file. Now, everything returns back to normal.

 

The extension and the restriction elements can be used to redefine the types, provided that the rules pertaining to them are not tampered with in the least. On replacing the 'redefine' element with the 'include' statement and eliminating the closing 'redefine' element, the following error is encountered:

 

b.xsd

...

<xs:include schemaLocation="b1.xsd" />

...

 

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException:

Unhandled Exception: System.Xml.Schema.XmlSchemaException: The 'http://www.w3.org/2001/XMLSchema:complexType' element is not supported in this context. An error occurred at file:///c:/xmlprg/b.xsd(3, 2).

 

The 'import' or 'include' elements cannot be used to redefine the existing types. However, the 'redefine' element can be used as a super-set of either an 'include' or an 'import' element, to either modify or change existing elements.

 

b.xsd

...

<xs:redefine schemaLocation="b1.xsd" >

<xs:complexType name="c2"/>

....

</xs:redefine>

...

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: No complex type to redefine. An error occurred at file:///c:/xmlprg/b.xsd(3, 2).

 

The 'redefine' element redefines an existing type, but it does not create a new one. In the b1.xsd file, only one type exists, viz. the type c1. The above error emerges when we attempt at creating a new type c2 using the 'redefine' element.

 

The 'redefine' element works in the same way as the 'include' element. Here, the schema being introduced must either exist in the same namespace as the redefining schema, or it should not belong to any namespace.

 

The type c1 in b1.xsd does not belong to any namespace, since the target namespace is empty. If the file b.xsd belongs to a namespace, such as abc, then the redefined type c1 would also fall in the abc namespace.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:redefine schemaLocation="b1.xsd">

<xs:complexType name="c1">

<xs:complexContent>

<xs:extension base="c2">

<xs:sequence>

..

..

</xs:sequence>

</xs:extension>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: If type is being redefined the base type has to be self-rereference. An error occurred at file:///c:/xmlprg/b.xsd(3, 2).

 

To redefine an existing type, the base attribute in the extension or the restriction element must also have the same type as the type that is being redefined. Redefining c1 with the base as c2 results in an exception. Note the word ‘self-rereference’ in the error message, a mistake committed by the developers at Microsoft.

 

Thus, by using redefine, the existent definition has now been annihilated, and only the new type definition i.e. c1, prevails. There is no means of accessing the old definition.

 

Substitution Groups

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element ref="aaa"/>

<xs:element ref="bbb"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="aaa" type="xs:string"/>

<xs:element name="bbb" type="xs:string"/>

<xs:element name="ccc" type="xs:string" substitutionGroup="aaa" />

<xs:element name="ddd" type="xs:string" substitutionGroup ="bbb" />

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

<bbb> 10 </bbb>

</zzz>

 

The above example has a root element zzz with an anonymous complexType. This type has two string type elements that refer to elements aaa and bbb, respectively. The elements aaa and bbb are placed as children to the schema. In the xml file, the zzz element is followed by the elements aaa and a bbb, in sequence.

 

b.xml

<?xml version="1.0"?>

<zzz>

<ccc> 10 </ccc>

<bbb> 10 </bbb>

</zzz>

 

The above xml file gives no error, even though aaa has been replaced by ccc. This comes about because the element ccc is provided with a substitutionGroup attribute, which is initialized to the element aaa. Thus, the aaa element can always be replaced with ccc. In other words, the element ccc can be used in place of aaa anywhere in the file.

 

b.xml

<?xml version="1.0"?>

<zzz>

<ccc> 10 </ccc>

<ddd> 10 </ddd>

</zzz>

 

Along the same lines, the ddd element has the attribute of the substitution group initialized to bbb, as a result of which, the bbb tag can now be replaced with the ddd tag in the xml file.

 

 b.xml

<?xml version="1.0"?>

<zzz>

<ccc> 10 </ccc>

<ddd> 10 </bbb>

</zzz>

 

Error

Unhandled Exception: System.Xml.XmlException: The 'ddd' start tag on line '4' doesn't match the end tag of 'bbb' in file 'file:///c:/xmlprg/b.xml'. Line 4, position 12.

 

What is not permitted is the fifty-fifty combination, i.e. element ddd cannot be the starting tag and the element bbb as the ending tag.

 

In the above program, the tag ddd has been used as the starting tag, whereas the tag bbb has been used as the ending tag. The above exception is bound to occur, since the creator of the xml file is not expected to use mismatched tags. He/She would not be aware that a substitution group is being dealt with, and not a normal tag.

 

<xs:element name="ccc" type="xs:integer" substitutionGroup="aaa" />

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: 'ccc' cannot be a member of substitution group with head element 'aaa'. An error occurred at file:///C:/xmlprg/b.xsd(12, 2).

 

The element aaa is of a string type. However, while creating the element ccc with the attribute of substitutionGroup initialized to aaa, the type is altered to integer. If an element is substituted for another, then both, the original and the substitute elements must have the same features, or else an error will result.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element ref="aaa"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="aaa">

<xs:simpleType>

<xs:restriction base="xs:integer">

<xs:maxExclusive value="100"/>

</xs:restriction>

</xs:simpleType>

</xs:element>

<xs:element name="ccc" type="xs:integer" substitutionGroup="aaa" />

</xs:schema>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: 'ccc' cannot be a member of substitution group with head element 'aaa'. An error occurred at file:///C:/xmlprg/b.xsd(12, 2).

 

In the above example, the element aaa is of simpleType and the base type is integer. It uses the restriction element to limit the range of the values to 100. 

 

The above error occurs when we attempt to make the element ccc as part of the aaa group.  Thus, only simple elements can be substituted by other elements.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa" type="xs:integer" />

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="ccc" type="xs:integer" substitutionGroup="aaa" />

</xs:schema>

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Reference to undeclared substitution group affiliation. An error occurred at file:///c:/xmlprg/b.xsd(9, 2).

 

Earlier, we had succinctly mentioned that the element name that is used in the substitutionGroup, must necessarily be a global one. In the above case, the element aaa is a local element, but it is part of the complexType element. Thus, the local elements can use the 'ref' attribute to refer to the global elements.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence maxOccurs="unbounded">

<xs:element ref="aaa"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="aaa" type="xs:string"/>

<xs:element name="bbb" type="xs:string" substitutionGroup="aaa" />

<xs:element name="ccc" type="xs:string" substitutionGroup="aaa" />

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa> 10 </aaa>

<bbb> 10 </bbb>

<ccc> 10 </ccc>

</zzz>

 

In the above example, the sequence has the maxOccurs attribute set to 'unbounded'. Thus, its contents can occur as many times as desired.

 

The sequence contains an element that refers to the element aaa, which is of type string. Besides the element aaa, which is declared to be of type string, there are two more elements, viz. bbb and ccc. Both these elements use the substitutionGroup attribute with the value of aaa. Thus, they can replace the element aaa in the xml file.

 

The xml file has the three elements aaa, bbb and ccc, placed in a sequence. Since the elements bbb and ccc can replace aaa, no errors are displayed.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence maxOccurs="unbounded">

<xs:element ref="bbb"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="aaa" type="xs:string"/>

<xs:element name="bbb" type="xs:string" substitutionGroup="aaa" />

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<bbb> 10 </bbb>

<aaa> 10 </aaa>

</zzz>

 

Error

Element 'zzz' has invalid child element 'aaa'. Expected 'bbb'. An error occurred at file:///c:/xmlprg/b.xml(4, 2).

 

The substitution group allows the use of the element bbb as the 'ref' value for an element. However, the reverse is not permitted. The element aaa can be replaced by bbb, but vice-versa is not permissible.

 

b.xsd

..

<xs:element name="aaa" type="xs:string" substitutionGroup="bbb"/>

...

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Circular substitution group affiliation. An error occurred at file:///c:/xmlprg/b.xsd(10, 2).

 

In the xsd file, the element aaa constitutes a part of the substitutionGroup bbb. Even though the element aaa has not been referred to anywhere in the file, an exception shows up. This is because the XML framework detects certain circular references, which are not acceptable in the least.

 

The main intent here is to have the element aaa replace the element bbb, and vice-versa. However, in XML, circular references are totally debarred.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence maxOccurs="unbounded">

<xs:element ref="aaa"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="aaa" type="c1"/>

<xs:element name="bbb" type="c2" substitutionGroup="aaa"/>

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="ccc" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:extension base="c1">

<xs:sequence>

<xs:element name="ddd" type="xs:string"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa>

<ccc />

</aaa>

<bbb>

<ccc />

<ddd />

</bbb>

</zzz>

 

The above example works in an accomplished manner, since the root element zzz has an element that refers to the element aaa. This element aaa has a type c1, which holds only the element ccc. This represents one of the simplest types that can ever be created. Thereafter, we encounter an element bbb of type c2, and a substitution group that points to aaa.

 

No error shows up when the type c2 derives from the type c1, and when it uses the extension mechanism to add the element ddd to the type c2. Thus, the type c1 contains only a single element ccc, whereas the type c2 has the two elements ccc and ddd.

 

In the xml file, the element aaa has one child element ccc. Then, since the element bbb can replace the element aaa, the element bbb is specified with its two constituent elements of ccc and ddd.

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa>

<ccc />

<ddd />

</aaa>

</zzz>

 

 

Error

Element 'aaa' has invalid child element 'ddd'. An error occurred at file:///C:/xmlprg/b.xml(5, 2).

The 'ddd' element is not declared. An error occurred at file:///C:/xmlprg/b.xml(5, 2).

 

The above error emanates from the fact that the element aaa cannot have a child element ddd. The element bbb can replace aaa, which in turn can enclose the tag ddd. Thus, using the substitutable element, we can place multiple child elements within the tag.

 

In XML parlance, the element that can be replaced is called a 'head element'. Thus, substitution allows one element to replace another.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="color" type="xs:string"/>

<xs:element name="colour" substitutionGroup="color" type="xs:string"/>

<xs:complexType name="c1">

<xs:sequence>

<xs:element ref="color"/>

</xs:sequence>

</xs:complexType>

<xs:element name="american" type="c1" />

<xs:element name="british" substitutionGroup="american" />

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<american>

<color/>

</american>

 

b.xml

<?xml version="1.0"?>

<british>

<colour/>

</british>

 

b.xml

<?xml version="1.0"?>

<british>

<color/>

</british>

 

Using the substitution group, applications that cater to a wider audience, can be created. For instance, the Americans spell the word colour as 'color', whereas the British spell it as 'colour'.

 

To accommodate both these spellings, we firstly create two global elements named 'color' and 'colour'. We make the element color as the group for the element of colour. As mentioned earlier, only global elements can be used in a substitutionGroup.

 

Then, a type c1 is created, which has an element that references color. Here, colour can also be used in place of color, because of the substitution group. The root element is specified as american having the type c1, so that it encloses both 'color' and 'colour' as its child elements.

 

Finally, one more global element called british is created. It has the same substitution group as american. Thus, now american and british are uniformly applicable in all circumstances.

 

Three XML files with different permutations and combinations have been stipulated above, though there could have been more. Thus, more the number of substitution groups, the larger would be the possible combinations. The applications of the substitution group are curtailed only by your imagination.

 

b.xsd

...

<xs:element name="colour" substitutionGroup="color" />

 

Since both the elements of 'colour' belong to the substitution group named color, they have the same type by default. Hence, the type attribute can be eliminated, as shown above.

 

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element ref="aaa"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="aaa" type="xs:string"/>

<xs:element name="bbb" type="xs:string" substitutionGroup="aaa" />

<xs:element name="ccc" type="xs:string" substitutionGroup="bbb" />

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<ccc/>

</zzz>

 

In the above example, aaa is the head element, and the element bbb is used to substitute it. Next, the element ccc is used to substitute the element bbb.

 

Thus, wherever aaa can be used, bbb can be used too; and wherever bbb can be used, the element of ccc can be used too. Resultantly, wherever aaa can be used, ccc too can be used, as is evident in the above xml file.

 

If you replace ccc with aaa or bbb in the xml file, no errors will result.

 

b.xsd

<?xml version="1.0"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element ref="aaa" maxOccurs="unbounded"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="aaa" abstract="true" type="xs:string"/>

<xs:element name="bbb" substitutionGroup="aaa" type="xs:string"/>

<xs:element name="ccc" substitutionGroup="aaa" type="xs:string"/>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<bbb />

<ccc />

<ccc />

</zzz>

 

The abstract attribute used in one of the previous chapters is used here too, with substitution groups.

 

The root element zzz has a child element that refers to aaa. But, this element aaa cannot be used since the abstract attribute is set to 'true'. Its maxOccurs attribute is set to 'unbounded' to facilitate the multiple occurrences of the element. Then, two more global elements named bbb and ccc are created, both of which have their substitution groups as aaa.

 

This allows the replacement of the element aaa with the element bbb or ccc, as many times as desired as clearly depicted in the xml file. Whenever the abstract property of an element is set to true, it cannot be used directly, though some other element can be used in its place.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa" type="c2"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:extension base="c1">

<xs:sequence>

<xs:element name="ccc" type="xs:string"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0" ?>

<zzz>

<aaa>

<bbb/>

<ccc/>

</aaa>

</zzz>

 

In the above example, the root element zzz contains an element aaa of type c2. This type c2 in turn derives from type c1, which has an element bbb. The type c2 has the type c1 as its base type. It adds one more element ccc to the type c2. This is nothing different from what we already know.

 

Modify the complexType definition for c1 by adding the attribute 'final' with a value of 'extension' assigned to it.

 

<xs:complexType name="c1" final="extension">

 

On doing so, the following exception is thrown:

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Base type is final extension. An error occurred at file:///c:/xmlprg/b.xsd(14, 2).

 

The 'final' attribute determines the constraints to be applied to the type while deriving other types.  Since the value assigned to 'final' is 'extension', the type cannot be used to extend other types. Thus, no type can now extend from this type.

 

Change the attribute value from 'extension' to 'restriction' and rewrite complexType c2 as follows:

 

b.xsd

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

</xs:restriction>

</xs:complexContent>

</xs:complexType>

 

The restriction element is used to restrict the entities. However, on modifying the complex type, the following exception is thrown:

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Base type is final restriction. An error occurred at file:///c:/xmlprg/b.xsd(14, 2).

 

Thus, a type can be extended or restricted by another type.

 

<xs:complexType name="c1" final="#all">:

 

The #all value applies to both, extension as well as restriction. And the same error is reported for both extension and restriction.

 

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" finalDefault="#all">

 

In the original program, add the attribute of finalDefault.

This attribute has the same functionality as the final attribute. However, 'finalDefault' works at the element level, whereas  'final' operates on the global level.

 

The ensuing effect of the attribute finalDefault on the schema is that, the attribute final=#all is added to all the elements that can accept such an attribute. Everything that can be done at a global level, can however be undone at the element level.

 

We had briefly touched upon the 'fixed' attribute earlier with reference to an element. Now, let us use 'fixed' in the context of derivations and data facets.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa" type="c1"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:simpleType name="c1">

<xs:restriction base="xs:string">

<xs:length value="3" fixed="true"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="c2">

<xs:restriction base="c1">

<xs:pattern value="[A-Z]{3}"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

 

b.xml

<?xml version="1.0" ?>

<zzz>

<aaa>ABC</aaa>

</zzz>

 

The above xsd file has a root element zzz, which has a child element aaa of type c1. This type is a simple type. It uses restriction to restrict the length to 3. There is one more type c2, which again is a simpleType and derives from the type c1.

 

The pattern restricts the values that the type c2 can handle, upto 3 capital letters only. We do not use this type at all. In the xml file, since the element aaa contains 3 capital letters, all is hunky-dory.

 

Modify the type c2 as follows:

 

b.xsd

<xs:simpleType name="c2">

<xs:restriction base="c1">

<xs:pattern value="[A-Z]{3}"/>

<xs:length value="3"/>

</xs:restriction>

</xs:simpleType>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Base type has {fixed} equal to true. An error occurred at file:///c:/xmlprg/b.xsd(17, 2).

 

On adding the data facet to the simpleType c2, an error occurs. This ensues because in the type c1, the fixed parameter is assigned the value of 'true', which signifies that no derived type can change the data facet value. The error occurs despite the length remaining the same.

 

A derived type cannot modify the value of the data facets. It can change all the other data facets, except the one having the attribute of fixed=true.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa" type="c2"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:simpleType name="c1">

<xs:restriction base="xs:string">

<xs:length value="3" fixed="true"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="c2">

<xs:restriction base="c1">

<xs:pattern value="[A-Z]{4}"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

 

b.xml

<?xml version="1.0" ?>

<zzz>

<aaa>ABC</aaa>

</zzz>

 

b.xml

<?xml version="1.0" ?>

<zzz>

<aaa>ABCD</aaa>

</zzz>

 

Error

The 'aaa' element has an invalid value according to its data type. An error occurred at file:///c:/xmlprg/b.xml(3, 12).

 

The glitch with the XML Schema world is that it does not perform any error checks for inconsistency.

 

In the above example, the element is derived from the type c2, which in turn restricts the type c1. In the type c1, the length is restricted to 3, while in the type c2, the pattern is restricted to four capital letters. Both these conditions need to be satisfied simultaneously.

 

Since both these conditions cannot be true concurrently, the above two XML files generate errors. This is because, each of them satisfy only one condition at a time.

The XML Schema world does not validate such logically inconsistent behaviour.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa" type="c1" />

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:complexType name="c1" >

<xs:sequence>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:extension base="c1">

<xs:sequence>

<xs:element name="ccc" type="xs:string"/>

</xs:sequence>

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

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

<aaa xsi:type="c2">

<bbb />

<ccc />

</aaa>

</zzz>

 

In the above xsd file, the root element zzz has a child element aaa of type c1, which in turn has an element bbb. Moreover, there exists a complexType c2 that extends the type c1 and the element ccc.

In the xml file, the xsi:type is used to change the type of aaa from c1 to c2. If the above program does not appear comprehensible and logical to you, please refer to the programs explained earlier. The pertinent question at this stage is - How do we prevent the XML user from changing the type c1 to the type c2 at runtime, or at the time of creating the xml file?

 

Error

Element 'aaa' has xsi:type derivation blocked. An error occurred at file:///c:/xmlprg/b.xml(3, 2).

The 'aaa' element is not declared. An error occurred at file:///c:/xmlprg/b.xml(3, 2).

 

This can be achieved by adding the attribute block=extension in the xsd file. This ensures that the xsi:type feature is blocked in the xml file. Thus, the user is forbidden from changing the run time type of the element.  Every feature offered by the XML world can be 'blocked', by implementing the blocking facility.

 

The xsi:type can also be initialized to the derived type.

 

Changing the above line to

 <xs:complexType name="c1" block="restriction">

 generates no errors, since the block applies to 'restriction' only. The #all blocks the usage of both, the extension as well as the restriction in a type.

 

<xs:complexType name="c2" block="extension">

 

On eliminating the block attribute from the type c1 and assigning it to the type c2, no errors are reported. This is because the block attribute does not work with retrospective effect. An exception would have occured in the xml file, had we created an element with the type of c2 and then, extended the type c3 from the type c2, followed by a change in the type to c3.

 

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" blockDefault="extension">

 

 

In the XML world, there exists an attribute called blockDefault at the schema level. Initializing this attribute to 'all' is akin to setting the block attribute individually for all elements, wherever it is applicable.

 

b.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="zzz" type="c2" />

<xs:complexType name="c1">

<xs:sequence>

<xs:element name="aaa" type="xs:string" minOccurs="0"/>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:complexType>

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<bbb/>

</zzz>

 

When the restriction clause is used, it must be implemented for all the elements that are present in the base type. In the above example, even though the aaa element is not repeated, all goes well. This happens because the attribute minOccurs has a value of 0 by default.

 

Thus, it does not have to occur in the base type c1. The default elements do not require to be placed in the derived type.

 

<xs:element name="aaa" type="xs:string"/>

Removal of the minOccurs attribute from the element aaa, as shown above, results in the particle error.

 

<xs:element name="aaa" type="xs:string" minOccurs="0" maxOccurs="0"/>

 

If the elements are disabled, i.e. if the minOccurs and maxOccurs are both assigned a value of 0, then they still have to appear in the type c2, using the restriction mechanism.

 

b.xsd

<xs:complexType name="c2">

<xs:complexContent>

<xs:restriction base="c1">

<xs:sequence>

<xs:element name="aaa" type="xs:string"/>

<xs:element name="bbb" type="xs:string"/>

</xs:sequence>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

 

However, introducing the element aaa in type c2, as seen above, displays the same old particle error. Thus, nobody can ever use an element whose minOccurs and maxOccurs, both have a value of 0. In the world of restriction, each and every element that is present in the base type, must be repeated in the derived type also, whether we like it or not.

 

At this juncture, let us clear the air with regard to declarations and definitions. A declaration is used for creating elements and attributes. These declarations are visible in the xml file or in the instance document. Whatever does not find a place in the instance document is called a definition.

 

Thus, simple types, complex types, attribute groups, et al, that are not present in the instance document, fall in the realm of definitions. In our book, both these terms have been used interchangeably.