4.
Derived Data Types
The singularly
most significant concept in the world of object-oriented programming is that of
'inheritance'. Here, a basic type is created and then, new types are fashioned
out of it by adding to or subtracting from the existing one. By modifying the
existing type, the work already accomplished by others in creating the
original, can be recycled. The original types too are re-used many times over.
To put it simply,
the most splendid feature of 'inheritance' or 'extension' is that work or
effort put in by other people can be modified and re-used with considerable
ease. This greatly adds to our convenience.
Let us take a
brief detour and discover how to extend or derive one type from another.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:sequence>
<xs:element name="ddd" type="c2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="c1">
<xs:sequence>
<xs:element name="aaa"
type="xs:string"/>
<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>
<ddd>
<aaa> </aaa>
<bbb> </bbb>
<ccc> </ccc>
</ddd>
</zzz>
The element ddd
is created within the root element zzz with the user-defined type of c2. The
'ref' attribute that we encountered in the earlier chapter generally refers to
an existing attribute or element, whereas here, we have used the type
attribute, which points to c2.
The type c2 is a
derived type that extends c1. Hence, initially type c1 is created as a
complexType containing the two elements aaa and bbb in a sequence.
Then, the type of
c2 is created, which again is a complexType. It is followed by the element
complexContent. The keyword 'extension' is used in lieu of 'restriction', with
the base value of c1. The base attribute clearly signifies that the type is
being extended or derived from type c1, which contains the two elements aaa and
bbb in a sequence. Another element ccc is created in the sequence to augment
the existing two elements.
Thus, any element
with a type of c2 would now consist of three elements, viz. the elements aaa
and bbb from c1 and the element ccc from c2.
In the above xml
file, the ddd element is furnished with the elements aaa, bbb and ccc below it.
No errors are generated.
b.xml
<?xml version="1.0"?>
<zzz>
<ddd>
<ccc> </ccc>
<aaa> </aaa>
<bbb> </bbb>
</ddd>
</zzz>
Error
Element 'ddd' has invalid child element 'ccc'. Expected
'aaa'. An error occurred at file:///C:/xmlprg/b.xml(4, 2).
Since the
elements are placed in a sequence, they have to be present in a specific order.
The above xml file is bound to generate errors, since the element ccc has been
placed at the beginning. Besides, even if a single element is omitted, an error
shall surface again. Thus, we have to maintain the same order as specified in
the xsd file.
In the above xsd
file, the element ddd is at the highest level. It has three elements as direct
child elements below it, all of which are at the same level. Thus, the elements
aaa, bbb and ccc are all at par. There is no way of distinguishing these child
elements from one another, with regard to the 'type' that they originate from.
The same result
can also be achieved by making the element ddd hold the three elements in an
anonymous complexType. Another possibility is to have a single type c1
consisting of three elements and then, assigning this type c1 to the element
ddd. The actual approach adopted in the file has no bearing on the xml file.
b.xsd
<xs:extension base="c1">
<xs:sequence>
<xs:element name="aaa"
type="xs:string"/>
</xs:sequence>
</xs:extension>
b.xml
<?xml version="1.0"?>
<zzz>
<ddd>
<aaa> </aaa>
<bbb> </bbb>
<aaa> </aaa>
</ddd>
</zzz>
In the xsd file,
the name of the third element is changed from ccc to aaa, but the type is
retained as it is. The xml file is also modified so that, instead of the
element ccc, the element aaa can be placed after bbb. Thus, even if we employ
identical names in the 'derived' or 'extension' class, the XML Schema does not
complain.
b.xsd
<xs:extension base="c1">
<xs:sequence>
<xs:element name="aaa"
type="xs:integer"/>
</xs:sequence>
</xs:extension>
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(19, 2).
Certain rules
have to be complied with at every stage. If we change the type of the new
element aaa from string to integer, an exception is hurled at us.
The exception
clearly construes the fact that the elements can be assigned the same name, as
long as the type remains the same. This implies that the schema world acknowledges
the difference between the two aaa elements only when they have the same type.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:sequence>
<xs:element name="ddd" type="c3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="c1">
<xs:sequence>
<xs:element name="aaa"
type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="c2">
<xs:complexContent>
<xs:extension base="c1">
<xs:sequence>
<xs:element name="bbb"
type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="c3">
<xs:complexContent>
<xs:extension base="c2">
<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>
<ddd>
<aaa> </aaa>
<bbb> </bbb>
<ccc> </ccc>
</ddd>
</zzz>
The above xsd
program may appear to be slightly protracted, but it really is not at great variance
from the earlier one. The complexType c1 is created to contain an element aaa,
and a complexType c2 is created to accommodate the element bbb. Since c2
extends from the type c1, it effectively contains the two elements aaa and bbb.
One more
complexType named c3 is created, which has its own element ccc, but it extends
c2. The main element ddd is assigned the type c3.
The xml file does
not generate any error as the three elements of aaa, bbb and ccc have been
specified in the correct sequence. It is perfectly valid for one type to derive
from another type, which in turn can be derived from another type, and so on.
The user is oblivious to this internal structure of the schema.
If an element is
to be disregarded, the most elementary solution is to make the minOccurs
parameter equal to 0. For instance,
<xs:element name="ccc" type="xs:string"
minOccurs="0"/>
Hereinafter, the
existence of the element ccc in the xml file becomes optional.
Now, undo the
above changes for ccc and assign the minOccurs clause to the element named bbb
as follows:
<xs:element name="bbb" type="xs:string"
minOccurs="0"/>
Now, enter the xml file as below:
b.xml
<?xml version="1.0"?>
<zzz>
<ddd>
<aaa> </aaa>
</ddd>
</zzz>
Error
Element 'ddd' has incomplete content. Expected 'bbb ccc'. An
error occurred at file:///c:/xmlprg/b.xml(5, 3).
Granting the
'optional' status to the element of bbb in the xml file does not result in
making ccc elective. This is because the type c2 is derived from c1.
b.xml
<?xml version="1.0"?>
<zzz>
<ddd>
<ccc> </ccc>
</ddd>
</zzz>
Error
Element 'ddd' has invalid child element 'ccc'. Expected
'aaa'. An error occurred at file:///C:/xmlprg/b.xml(4, 2).
Placing only the
element ccc in the xml file also spawns an error, since the element aaa is
conspicuous by its absence. Thus, if an element is made 'default', this action
has no link with the other elements that derive from it.
b.xml
<?xml version="1.0"?>
<zzz>
<ddd>
<aaa> </aaa>
<ccc> </ccc>
</ddd>
</zzz>
On introducing
the element aaa in the file, the exception vanishes. Thus, every individual
element must have a minOccurs attribute or any other attribute set
individually.
<xs:extension base="c1" minOccurs="0">
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
The 'minOccurs' attribute is not supported in this context. An error occurred
at file:///c:/xmlprg/b.xsd(16, 26).
The minOccurs
attribute can neither be set at the extension level, nor at the complexContent
level, and also not at the complexType level. The complex type with a name has
a default built-in entry for the attribute.
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:schema>
b.xml
<?xml version="1.0" ?>
<zzz>
<aaa>
<bbb/>
</aaa>
</zzz>
In the above xsd
file, the types have been re-used. The type c1 has an element bbb, which is
assigned to the child element aaa within the root element zzz. Thus, in the xml
file, the element aaa can now contain the element bbb.
Here, modify the
‘complexType name=c1' statement in the xsd file to contain the 'abstract'
attribute as follows:
<xs:complexType name='c1' abstract="true">
On doing so, the
following exception is produced:
Error
Element 'aaa' is or it's type is abstract. 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).
The 'bbb' element is not declared. An error occurred at
file:///C:/xmlprg/b.xml(4, 2).
The error clearly
indicates that if complexType c1 is 'abstract', then the type cannot be used
directly for any element. The appropriate approach is illustrated in the next
program.
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"
abstract="true">
<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, like before, the type c1 is assigned the abstract attribute. Thus, the
type cannot be used directly.
Now, the type c2
is created. It commences with the complexType type tag, followed by a
complexContent element. Then, it uses the 'extension' element to derive from
the abstract type c1. Within the sequence element, one more element named ccc
is added. Thus, the aaa type contains the two elements aaa, bbb and ccc from
the abstract types c1 and c2, respectively.
The rationale
behind using the 'abstract' type is that it cannot be used directly since it is
incomplete. Therefore, the user is compelled to add a few more elements to the
existing one. This is akin to using abstract classes in object oriented
programming languages.
The 'type'
attribute can either take a simpleType or a complexType as its value. So, in
that sense, the system does not differentiate between them. The complexType can
contain any one of the six following types of entities at any given time:
· First is the 'simpleContent' element,
which permits the complexType to contain character data or a simpleType, but
does not allow any elements.
· Second is the 'complexContent'
element, which only allows elements.
· Third is the 'group' entity, which
permits elements that are referenced from a group.
· Fourth is the 'sequence' entity,
which uses elements in a specified order.
· Fifth is the 'choice' entity, which
allows only one of the elements to be selected.
· Sixth is the 'all' element, which
enables us to use any or all of the elements in any order that we desire.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:sequence>
</xs:sequence>
<xs:choice>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
The content model of a complex type must consist of 'annotation'(if present)
followed by zero or one of 'simpleContent' or 'complexContent' or 'group' or
'choice' or 'sequence' or '
all' followed by zero or more attributes or attributeGroups
followed by zero or one anyAttribute. An error occurred at
file:///C:/xmlprg/b.xsd(6, 2).
In a complexType,
a sequence and a choice cannot be present simultaneously.
Consequently, the
complexType can contain only one of the following six elements: simpleContent,
complexContent, group, sequence, choice and all, as has been mentioned in the
error.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="aaa"
type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz>
<aaa>aaa</aaa>
<aaa>123</aaa>
</zzz>
The element and
attribute tag contain a 'type' attribute, which determines the type of content
that can be used with the element.
Thus, if an
element has the type integer, the content between the elements cannot be a
string. It has to be an integer. All the simple, complex and built-in types are
derived from an abstraction type, which is the base type for all types.
The type anyType
represents the above abstraction. This type does not place any restrictions on
the content that can be used. Therefore, the content type is not checked. Thus,
whenever the flexibility to use any type of content is desired, the element or
attribute uses the 'anyType' type. It can be used wherever the other types are
used.
b.xsd
<xs:element name="aaa"/>
By default, the
type is anyType. Thus, if the type has not been specified, the type for the
element defaults to anyType.
In the earlier
examples, it was the Occurs family of attributes that determined the occurrence
or frequency of the elements. The next series of programs applies these
constraints to a group of elements.
The XML Schema
allows us to handle a group of elements as a single entity, so that the
constraints can be applied to the entire group in a single stroke. In the XML
1.0 world, these were known as 'parameter entities'.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:choice>
<xs:group
ref="bb"/>
<xs:element name="ccc"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:group name="bb">
<xs:sequence>
<xs:element name="aaa" />
<xs:element name="bbb"/>
</xs:sequence>
</xs:group>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz>
<aaa>aaa</aaa>
<bbb>123</bbb>
</zzz>
In the xsd file,
we encounter a new element called 'group'. By using the name attribute, a name
is assigned to the group. The task of a group element is to place multiple
declarations of elements together, so that they can be assigned to a
complexType element concurrently.
The complexType
element is created without a name and then, it is followed by a choice element.
In the above example, one can choose between either the group element or the
element name ccc. The group element refers to an existing group, which in our
case is known as bb. The xml file works fine, since it contains the two
elements aaa and bbb from the group bb.
b.xml
<?xml version="1.0"?>
<zzz>
<ccc>aaa</ccc>
</zzz>
As mentioned
earlier, the choice element provides an option of picking one out of the two
elements. The xml file works very well when the element ccc is selected instead
of the group bb.
b.xml
<?xml version="1.0"?>
<zzz>
<aaa>123</aaa>
<bbb>123</bbb>
<ccc>aaa</ccc>
</zzz>
Error
Element 'zzz' has invalid child element 'ccc'. An error
occurred at file:///C:/xmlprg/b.xml(5, 2).
The above xml
file contains the group elements as well as the element ccc. This is
unacceptable, since the xsd file contains a 'choice' element and not a
'sequence' element. By replacing the 'choice' element with a 'sequence'
element, this error gets addressed. But now, the earlier two XML files display
errors.
The group
element
A group
represents a collection. A group element simply gets replaced with its
constituent elements.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:group ref="bb"/>
<xs:attribute name="a1"/>
</xs:complexType>
</xs:element>
<xs:group name="bb">
<xs:sequence>
<xs:element name="aaa" />
<xs:element name="bbb"/>
</xs:sequence>
</xs:group>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz a1="hi">
<aaa>aaa</aaa>
<bbb>aaa</bbb>
</zzz>
Since a group is
a collection of elements, it tends to make life hassle-free, as there is no
further necessity for either a sequence or a choice. The root tag zzz now
possesses two elements due to the group element. Bear in mind that the element
of attribute a1 following the group, applies to the zzz element.
A group contains
nothing but the elements. Therefore, placing a set of attribute elements in a
group definition would generate an exception. The elements in the group should
be used in the same sequence in which they are written. So, exchanging the aaa
element with bbb in the xml file is a sure sign of impending disaster.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:sequence>
<xs:group name="bb">
<xs:sequence>
<xs:element name="aaa" />
<xs:element name="bbb"/>
</xs:sequence>
</xs:group>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
The 'name' attribute is not supported in this context. An error occurred at file:///c:/xmlprg/b.xsd(5,
12).
The above error
occurs because a group definition with the complexType element has a local
declaration and not a global one. A group can only be created at a global
level, and not as the child of anything other than the schema element. In other
words, a group definition cannot be 'inlined'. It has to be created globally
and then referenced when desired.
The all
element
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:all>
<xs:element name="aaa"/>
<xs:element name="bbb"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz>
<bbb>aaa</bbb>
<aaa>aaa</aaa>
</zzz>
The 'all' element
acts like a group. However, it sternly imposes a restriction on the elements,
decreeing that they could either appear once or never. However, there is no
established sequence of appearance. Thus, even though the bbb element appears
before aaa in the xml file, no exception is generated.
There are three
attributes that can be used with this element. The first attribute is 'id',
which has the same implication everywhere, i.e. it should be unique or
different from the rest.
The minOccurs attribute
represents the minimum number of times that the element must appear. Its value
may either be 0 or 1. The default value is 1. Thus, if we eliminate the element
aaa from the xml file, an error emanates. In order to banish the error, modify
the statement containing the element aa, as shown below.
<xs:element name="aaa" minOccurs="0"/>
b.xml
<?xml version="1.0"?>
<zzz>
<aaa>aaa</aaa>
<aaa>aaa</aaa>
<bbb>aaa</bbb>
</zzz>
Error
Element 'aaa' cannot appear more than once in an all content
model. An error occurred at file:///c:/xmlprg/b.xml(4, 2).
The maxOccurs
attribute and the minOccurs attribute have default values of 1, implying that
the element must occur once and only once. The above xml file generates an
error, since the element aaa appears twice. To eradicate the error, add the
maxOccurs attribute to the element aaa in the xsd file, as shown here.
<xs:element name="aaa" minOccurs="0"
maxOccurs="3"/>
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
The {max occurs} of all the particles in the {particles} of an all group must
be 0 or 1 An error occurred at file:///c:/xmlprg/b.xsd(5, 2).
The error is a
clear indication that the attribute maxOccurs cannot have a value of 3, since
the value must be either 0 or 1. The basic rule encompassing all the elements
is that the elements within them may either appear, or they have the option of
being completely absent. However, if they do appear, then they cannot occur
more than once. The sequence of appearance is flexible.
The most
important feature of the 'all' element is that it does not enforce any specific
order.
The 'all' group
is a simplified version of the SGML &- Connector. This element can only be
positioned at the top level of a content model. The entities contained within
it must be individual elements. As pointed out earlier, the elements cannot
make more than one appearance. However, it is acceptable if they do not show up
at all.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:all>
<xs:element name="aaa" minOccurs="0"
/>
<xs:element name="bbb" minOccurs="0"
/>
</xs:all>
<xs:sequence>
<xs:element name="ddd"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
The content model of a complex type must consist of 'annotation'(if present)
followed by zero or one of 'simpleContent' or 'complexContent' or 'group' or
'choice' or 'sequence' or '
all' followed by zero or more attributes or attributeGroups
followed by zero or one anyAttribute. An error occurred at
file:///c:/xmlprg/b.xsd(8, 2).
The rules
pertaining to the 'all' group do not extend the liberty of creating elements or
sequences outside the 'all' group. The element aaa must appear as the only
child at the beginning of the content model. The other restriction is that it
can occur only once in a group, but it can occur multiple times in a schema.
It can occur with
the parent elements of group, extension, restriction and complexType. In our
case, the element appears within the complexType. The only elements that can be
placed within it are the element and the annotation. Annotation is used
primarily for documentation purposes.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz" type="c1">
</xs:element>
<xs:complexType name="c1">
<xs:complexContent>
<xs:extension base="c2">
<xs:all>
<xs:element name="aaa"/>
<xs:element name="bbb"/>
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="c2">
<xs:complexContent>
<xs:extension base="c3">
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="c3">
</xs:complexType>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz>
<aaa />
<bbb />
</zzz>
In the above xsd
file, the root element is of type c1. Now, merely for the sake of innovation,
the end element is placed on a new line, instead of being placed on the same
line. Then, a complex type c1 is created, which uses complexContent to extend
type c2.
This element then
ushers in the 'all' element to include the two elements of aaa and bbb, in any
sequence.
The complexType
c2 merely uses complexContent to extend from the type c3, which is devoid of
all elements. Incorporate the following changes to the type c2:
b.xsd
<xs:complexType name="c2">
<xs:complexContent>
<xs:extension base="c3">
<xs:sequence>
<xs:element name="ccc"
type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
'all' is not the only particle in a group or being used as an extension. An
error occurred at file:///c:/xmlprg/b.xsd(7, 2).
In the above
program, the element ccc is appended in sequence. The above error crops up
because a complexType that uses the 'all' element cannot extend from a
complexType that already contains some content.
b.xsd
<xs:complexType name="c2">
<xs:sequence>
<xs:element name="ccc"
type="xs:string"/>
</xs:sequence>
</xs:complexType>
The complexType
c2 can be made much simpler than what has been delineated in the earlier case.
The main consideration is that no elements or content can be specified in the
complexType, if the type that derives from it contains the element.
b.xsd
<xs:complexType name="c2">
<xs:attribute name="ccc"
type="xs:string"/>
</xs:complexType>
However, the
presence of an attribute does not trigger any error.
b.xml
<?xml version="1.0"?>
<zzz ccc="hi">
<aaa />
<bbb />
</zzz>
This attribute
applies to the zzz or root element.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:attributeGroup ref="c1"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="c1">
<xs:attribute name="a1"
type="xs:string"/>
<xs:attribute name="a2"
type="xs:string"/>
</xs:attributeGroup>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz a1="hi" a2="bye" />
Elements have
attributes, but the reverse is not possible. Thus, dealing with groups of
elements is considerably distinct from handling groups of attributes.
The xsd file
starts with the element attributeGroup that is assigned the name c1. Then, two
attributes are placed to declare the attributes of a1 and a2.
In the element
zzz, the attributeGroup element is placed within the complexType, thereby
associating two attributes a1 and a2 with the element zzz in one direct shot.
The familiar rules about attributes hold good here too, i.e. the attributes are
optional and the sequence need not be maintained.
The element
attributeGroup is created for the attribute group with a name attribute. The
element then uses 'ref' to reference the attribute.
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="bbb"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="c1">
<xs:attribute name="a1"
type="xs:string"/>
<xs:attribute name="a2"
type="xs:string"/>
</xs:attributeGroup>
<xs:complexType name="bbb">
<xs:attributeGroup ref="c1"/>
</xs:complexType>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz>
<aaa a1="hi" a2="bye"></aaa>
</zzz>
The above program
is a simple extension of the earlier program. The attributeGroup c1 is created
with two attributes of a1 and a2. Then, a complexType bbb is created with the
attributeGroup element within it.
Using the 'ref'
attribute, the element is assigned the attributeGroup c1. Thus, any type that
refers to bbb shall contain the two attributes of a1 and a2.
The root element
aaa contains a complexType and a sequence. Then, an element aaa with the type
bbb, is created. Thus, the element aaa now has two attributes, a1 and a2.
Change the
complexType bbb as follows:
b.xsd
<xs:complexType name="bbb">
<xs:sequence>
<xs:element name="ccc"
type="xs:string"/>
</xs:sequence>
<xs:attributeGroup ref="c1"/>
</xs:complexType>
An element ccc is
added under the mandatory 'sequence' element. The correct xml file should read
as follows:
b.xml
<?xml version="1.0"?>
<zzz>
<aaa a1="hi" a2="bye">
<ccc> no </ccc>
</aaa>
</zzz>
This
substantiates the fact that an attribute group can be added along with the
elements in a complexType. The whole concept behind having attributes within a
group is that, it ushers in simplicity and ease of handling a whole group, as
against grappling with each attribute individually.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz">
<xs:complexType>
<xs:attributeGroup ref="c2"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="c1">
<xs:attribute name="a1"
type="xs:string"/>
<xs:attribute name="a2"
type="xs:string"/>
</xs:attributeGroup>
<xs:attributeGroup name="c2">
<xs:attributeGroup ref="c1"/>
<xs:attribute name="a3"
type="xs:string"/>
</xs:attributeGroup>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz a3="hi" a1="no"
a2="yes"/>
In the above
example, two attributeGroup elements have been created. The attributeGroup c1
has the same attributes of a1 and a2. The second attributeGroup named c2, uses
'ref' to refer to the group c1. It contains one more attribute of c3. Thus,
attributeGroup c2 has a total of three attributes, viz. a1, a2 and a3. The root
element zzz is then assigned this attribute group of c2.
In the xml file,
the order of the attributes is of no relevance at all. The above program can be
treated as an exercise in recursion.
The
attributeGroup element takes three attributes, viz. id, name and the ref
attribute. It is obvious that the name and the ref attributes cannot occur
together. Let us examine the following statement from the above program:
<xs:attributeGroup name="c2">
<xs:attributeGroup ref="c1"/>
This statement
illustrates that the attributeGroup can possess either the 'name' attribute or
the 'ref' attribute.
We have already
stumbled upon instances where these attributes have been used with the parent
elements of attributeGroup, complexType and schema. The elements that fall
under these parent elements are 'attribute' and 'annotation'. Thus, the
attributeGroup c1 is defined as a child of the schema element.
Every attribute
is normally assigned a name at the time of creation. The use of the name
attribute with attribute and attributeGroup elements has already been examined
in the earlier examples.
In case the 'ref'
attribute is used, it should be present under either of these three, viz. an
attributeGroup or a complexType element or anyAttribute. The attributeGroup
element cannot have any content. Therefore, it should be empty.
The solitary idea
of using an attributeGroup is to ameliorate the readability of the schema. The
attributeGroup is used in various locations of the schema, as well as in
different schemas. Thus, changes have to be incorporated only at one place,
which would automatically get reflected in all the group elements that
reference them.
The
attributeGroup can be placed either at the beginning, or at the end of the
document.
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:string"
nillable="true"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz>
<aaa xsi:nil="true"></aaa>
</zzz>
Error
Unhandled Exception: System.Xml.XmlException: 'xsi' is an
undeclared namespace. Line 3, position 6.
The above xml
file throws an exception, stating that xsi is an undeclared namespace. In the
xsd file, the namespace of xs points to a URI. However, there is no mention of
the xsi namespace.
To remedy the
above error, the xml file has to be modified to contain the following:
b.xml
<?xml version="1.0" ?>
<zzz
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<aaa xsi:nil="true"></aaa>
</zzz>
Thus, all the
errors are eliminated.
The changes are
to be introduced to the xml file and not to the xsd file, since the xsi
namespace is utilized in the xml file, and not in the xsd file.
The next step is
to discern the 'nillable' attribute. On numerous occasions, at the time of data
entry into a form, certain values that are to be entered are indeterminable.
This non-availability of data could be attributed to a number of reasons, such
as unknown information or inapplicable information. This unfurnished or unknown
data should be represented in a distinguishable manner. While handling
databases, the 'null' concept comes into play under such circumstances.
In XML, the 'nil'
mechanism plays a role analogous to the 'null' concept. Thus, an element can
appear with or without a value. This 'nil' mechanism is termed as an 'out of
band signal'. Akin to the database methodology, where a field is assigned a
value of null, XML too uses the 'nil' attribute to signify that the element has
a null value.
If the 'nillable'
attribute is set to a value of 'true', no content can be added between the
elements. The xml file has an element aaa with the attribute called 'nil',
which is present in the xsi namespace. Thus, using the 'nillable' attribute in
the xsd file is equivalent to creating a nil attribute in the xml file. No
errors are visible since no content has been added between the aaa tags.
b.xml
<?xml version="1.0" ?>
<zzz
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<aaa xsi:nil="true"> hi </aaa>
</zzz>
Error
Element 'aaa' must have no character or element children. An
error occurred at file:///c:/xmlprg/b.xml(3, 21).
The error
witnessed above is inevitable since some content has been inserted between the
element aaa. The nil=true categorically implies that the above element has a
null value and therefore, must not be assigned any content.
On removing the
attribute xsi:nil="true", the error vanishes.
<xs:element name="aaa" type="xs:string"
/>
We have removed
the attribute nillable=true from the element aaa in the xsd file, as shown
above. Further, in the xml file, we have entered the following:
xsi:nil=true"
attribute as :
<aaa xsi:nil="true"> hi </aaa>
On doing so, the
following error is reported.
Error
If the 'nillable' attribute is false in the schema, then the
'xsi:nil' attribute must not be present in the instance. An error occurred at
file:///c:/xmlprg/b.xml(3, 2).
Thus, the
nillable attribute can be used to represent null values for an element. The nil
attribute is part of the namespace http://www.w3.org/2001/XMLSchema-instance.
To reiterate, the xsi namespace is merely a convention. Any other name too
would have sufficed.
This nil
mechanism applies only to elements and not to attributes, since only an element
can have a null value, while simultaneously having attributes containing their
own values. Null elements and attributes have no inter-connection whatsoever.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz"/>
<xs:complexType name="c1">
<xs:complexContent>
<xs:extension base="xs:string" />
</xs:complexContent>
</xs:complexType>
</xs:schema>
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
Undefined complexType 'http://www.w3.org/2001/XMLSchema:string' is used as a
base for complex type extension". An error occurred at
file:///c:/xmlprg/b.xsd(5, 2).
Simple types and
complex types cannot be substituted for each other. In a complexType, the
complexContent element is used to extend another type using the 'extension'
element. While the base attribute requires a complexType, it has been supplied
with the simple built-in type of 'string' instead.
Thus, an error is
reported since simple types and complex types cannot be interchanged with each
other.
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:element name="bbb" type="c11" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="c1">
<xs:complexContent>
<xs:extension base="c2" />
</xs:complexContent>
</xs:complexType>
<xs:complexType name="c2">
<xs:attribute name="aa" />
</xs:complexType>
<xs:simpleType name="c11">
<xs:restriction base="c22" />
</xs:simpleType>
<xs:simpleType name="c22">
<xs:restriction base="xs:integer" />
</xs:simpleType>
</xs:schema>
b.xml
<?xml version="1.0"?>
<zzz>
<aaa aa="hi"/>
<bbb>10</bbb>
</zzz>
In the above example,
the root tag zzz is followed by a sequence. The sequence offers two elements,
viz. aaa and bbb, both of type attribute. The element aaa is of complexType c1,
which uses complexContent to extend from type c2, which is also a complexType.
This type c2 merely adds the attribute of aa. Therefore, in the xml file, the
element aaa is provided with the attribute aa.
The element bbb
has a type c11, which is a simpleType. This is simply to reaffirm that the type
of an element can either be a simpleType or a complexType. In simpleType c11,
the restriction is placed on simpleType c22. The type c22 is used as a base. It
comprises of an integer. Thus, the element bbb is capable of containing only
integers.
Here, the string
c11 can be used in two situations: Firstly, as a placeholder in the element
type bbb, and secondly, while creating the simpleType c11. Now, change the
string c11 to c1 as revealed below.
b.xsd
<xs:element name="bbb" type="c1" />
<xs:simpleType name="c1">
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
The SimpleType 'c1' has already been declared. An error occurred at
file:///c:/xmlprg/b.xsd(18, 2).
The above error
is bound to occur since a simpleType and a complexType cannot share the same
name. They both use the same namespace to store the names of the types.
Thus,
occasionally, the XML framework examines whether the type is simple or complex.
The framework never permits the creation of a simple and complex type, with
both sharing the same name.
b.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="zzz" />
<xs:complexType name="c1" />
<xs:simpleType name="c1">
<xs:restriction base="xs:integer" />
</xs:simpleType>
</xs:schema>
Error
Unhandled Exception: System.Xml.Schema.XmlSchemaException:
The simpleType 'c1' has already been declared. An error occurred at
file:///c:/xmlprg/b.xsd(4, 2).
The above program
is a simplified version of the previous program, which was a long-drawn-out
one.