3.

Attributes

 

The behaviour of the elements can be changed depending on the values assigned to the attributes. Unlike an element, an attribute may or may not occur. But when the attributes are present, they rule the existence of the element. For instance, an element can occur in an xml file, provided the value of the attribute minOccurs is 1 or more. By default, both minOccurs and maxOccurs have a value of 1. Therefore, they can be utilized only once.

 

This chapter looks at the different attributes that can be assigned to the elements in the xsd file and how they affect each of them.

 

b.xml

<?xml version="1.0"?>

<zzz aa="hi"/>

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="ppp">

<xs:complexType >

<xs:attribute name="aa">

<xs:simpleType>

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

</xs:restriction>

</xs:simpleType>

</xs:attribute>

</xs:complexType>

</xs:element>

<xs:element name="zzz">

<xs:complexType>

<xs:attribute ref="aa" />

</xs:complexType>

</xs:element>

</xs:schema>

 

a.cs

using System;

using System.Xml;

using System.Xml.Schema;

public class zzz

{

public static void Main()

{

XmlTextReader r = new XmlTextReader("b.xml");

XmlValidatingReader v = new XmlValidatingReader(r);

v.ValidationType = ValidationType.Schema;

XmlSchemaCollection c;

c = v.Schemas;

c.Add(null, "b.xsd");

v.ValidationEventHandler += new ValidationEventHandler(abc);

while(v.Read()) ;

}

public static void abc(object s, ValidationEventArgs a)

{

Console.WriteLine(a.Message);

}

}

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: The 'aa' attribute is not declared. An error occurred at file:///c:/xmlprg/b.xsd(15, 2).

 

In the xsd file, element ppp propels forward with a complex type, which has an attribute called aa located within it. Since it is sited within the element ppp, it can only be referenced by elements within ppp. An attempt to access it from within the element zzz generates an exception, as shown above. If the attribute is made global, as is seen in the earlier examples, then it can be accessed from zzz too.

 

We would recommend that the attributes of minOccurs and maxOccurs should be initialized when the frequency of occurrence is being decided. The syntax for specifying the frequency of attributes is at great variance from that of the elements.

 

The program a.cs has been reproduced here. This program displays the error messages if any while validating the xml file with the schema definition.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa" type="xs:string" />

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz />

 

The above example does not display any error because by default, the use of the attribute is optional. Thus, it is at the discretion of the coder to either insert an attribute aa with the element zzz, or to desist from doing so.

 

Modify the attribute line in the xsd file to the following:

 

b.xsd

....

<xs:attribute name="aa" type="xs:string" use="prohibited"/>

b.xml

<?xml version="1.0"?>

<zzz aa="hi"/>

 

Error

The 'aa' attribute is not allowed. An error occurred at file:///c:/xmlprg/b.xml(2, 6).

 

The 'use' attribute assumes one of the three different values. The first such value is 'prohibited'. It forbids the presence of the attribute definition, as notified by the error message.

 

Thus, if an attribute is created, and for some reason, it is not required, it can be marked as 'prohibited'.

 

b.xsd

...

<xs:attribute name="aa" type="xs:string" use="optional"/>

 

By default, the 'use' attribute has the value of 'optional'. Thus, in the above xsd file, it is redundant to assign the value of 'optional' to the 'use' attribute. The 'optional' value leaves the discretion to the user to implement the attribute with the element.

 

On numerous occasions, the attribute is not implemented. In such cases, the element must have a default value. This feature is implemented by assigning a value to the default attribute. The default attribute can be assigned a value only when its use is optional.

 

b.xsd

...

<xs:attribute name="aa" type="xs:string" default="sonal"/>

 

b.xsd

...

<xs:attribute name="aa" type="xs:string" use="required" />

 

The required clause mandates the use of the attribute. Besides, if the 'value' attribute is present together with it, then the attribute that is present must have the value contained in the 'value' attribute. The attribute can be assigned a value if the 'value' attribute is not used.

 

An attribute coalesces a name and a type. The type definition for the type can either be a simple type or a built-in data type. The types can be present either with a global scope or can be located within complex types.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa" type="xs:integer" />

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz aa="10 23 45"/>

 

Error

The 'aa' attribute has an invalid value according to its data type. An error occurred at file:///c:/xmlprg/b.xml(2, 6).

 

The above xml file contains the values 10 23 45. These values do not match the data type integer, since an integer is made up of only a single number.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa">

<xs:simpleType>

<xs:list itemType="xs:integer"/>

</xs:simpleType>

</xs:attribute>

</xs:complexType>

</xs:element>

</xs:schema>

 

In the above example, the attribute tag does not terminate on the same line. Instead, it has a simpleType following it. Within this element, a list element is specified, with the itemType attribute pointing to a datatype.

 

The example justifies that attribute 'aa' can now embody a list of integer values. Thus, the list created in the xml file can contain integers such as 10, 23 and 45. This attribute can either have a built-in type or a simpleType created elsewhere.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:simpleType name="ttt">

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

<xs:maxInclusive value="1000"/>

</xs:restriction>

</xs:simpleType>

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa">

<xs:simpleType>

<xs:list itemType="ttt"/>

</xs:simpleType>

</xs:attribute>

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz aa="10 23 45"/>

 

Here, the itemType attribute is not an integer but a user defined simpleType ttt. This type permits integer values that lie within the upper limit of 1000.

Note that the type is specified as ttt and not as xs:ttt, since the xs namespace does not contain the type ttt.

 

b.xml

<?xml version="1.0"?>

<zzz aa="1100 23 45"/>

 

Error

The 'aa' attribute has an invalid value according to its data type. An error occurred at file:///c:/xmlprg/b.xml(2, 6).

 

The above xml file spawns the following error since the first value is larger than 1000. These error checks can be incorporated with effortless ease.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa">

<xs:simpleType>

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

<xs:enumeration value="b1"/>

<xs:enumeration value="b2"/>

<xs:enumeration value="b3"/>

</xs:restriction>

</xs:simpleType>

</xs:attribute>

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz aa="b3"/>

 

While stipulating the value of an element or an attribute, we may wish to restrict the choice to just a couple of options. The enumeration element helps us in achieving this.

The xsd file has three enumerations, each containing three different values of b1, b2 and b3, which can be assigned to the attribute aa. This element has to be placed within the 'restriction' element since the base data type can be specified along with such an element. Also, the restriction falls within the category of a simpleType element.

 

This is yet another way of regulating the data that the type can represent.

 

b.xml

<?xml version="1.0"?>

<zzz aa="b4"/>

 

Error

The 'aa' attribute has an invalid value according to its data type. An error occurred at file:///c:/xmlprg/b.xml(2, 6).

 

The above xml file spews forth the following error because the valid or acceptable values are b1, b2 or b3, whereas the string b4 does not fall within this range of acceptable values for the attribute aa.

 

This facet cannot confine the data carried by the boolean data type. But, the various values assigned to the multiple enumeration types must be unique, or else an error emanates.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa">

<xs:simpleType>

<xs:union memberTypes="bb cc" />

</xs:simpleType>

</xs:attribute></xs:complexType>

</xs:element>

<xs:simpleType name="bb">

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

<xs:maxInclusive value="100"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="cc">

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

<xs:enumeration value="b1"/>

<xs:enumeration value="b2"/>

<xs:enumeration value="b3"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

 

The above program demonstrates how a range of values can be used for an attribute. Thus, either a number less than 100, or the words b1, b2 or b3 can be entered.

 

The two XML files given below satisfy all the conditions.

 

b.xml

<?xml version="1.0"?>

<zzz aa="12"/>

 

The integer value is less than 100.

 

b.xml

<?xml version="1.0"?>

<zzz aa="b2"/>

 

The value has to be either b1, or b2 or b3.

 

b.xml

<?xml version="1.0"?>

<zzz aa="1200"/>

 

This xml file fails the test, since the value is greater than 100, and hence, it is out of the range.

 

b.xml

<?xml version="1.0"?>

<zzz aa="b4"/>

 

The value of b4 does not fit the bill either.

b.xml

<?xml version="1.0"?>

<zzz aa="12 b4"/>

 

The value assigned to the attribute may either be less than 100, or may be any one of the values b1, b2 or b3. It cannot have two values assigned to it.

 

Now, let us unravel the xsd file. Within the simpleType, a new element called 'union' has been employed :

<xs:union memberTypes="bb cc" />

 

 A union is like marriage. My wife and me, are two separate entities, but have a common bond of love.

 

The memberTypes attribute specifies the list of types that the attribute can contain. In our case, the value of the attribute can emanate either from the type bb or the type cc, but not from both. Thereafter,  the simpleType, bb and cc are defined in the file, as specified earlier.

 

Thus, a union is a compilation of values from a data source. It forms a catalogue of all the values that the individual data types can possess. Using a built-in type, such as a string, would defeat the very purpose of having such a structure, since any string value can then be used.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa">

<xs:simpleType>

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

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

</xs:restriction>

</xs:simpleType>

</xs:attribute>

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz aa="AB-5"/>

 

There are myriad features that can be used to assign values to attributes. The one used in the above example is called a 'pattern'. This facet has a value attribute and is passed a regular expression.

 

A regular expression consists of queer looking characters, which specify in a generic terms, as to what the user can key in. Because of the above pattern, the attribute aa can only have values consisting of two capital letters of the alphabet, followed by a minus sign, and finally followed by a single numeric digit. This is a tall order indeed.

 

Now. Let us examine the regular expression "[A-Z]{2}-[0-9]".

The syntax [A-Z] symbolizes a capital letter between A and Z. The number 2 within the curly braces {2} signifies 2 occurrences of the previous kind, thus representing 2 capital letters. Symbols such as - have no special significance and are taken at face value. Finally, the expression ends with a single digit ranging between 0 and 9, represented by [0-9].

 

People have written volumes on 'regular expressions'. We have also done so in one of our earlier books. This explains our reluctance to expound the whole concept all over again.

 

The core logic here is that whenever a value has to match a specific pattern, a regular expression is used. Thus, it becomes much easier to verify the user's inputs, such as a valid E-Mail address. Some examples of invalid values for the attribute aa are:

-           AB2      The minus sign is missing.

-           AB-      There is no ending digit.

-           aB-3     The small letter 'a' has been used in lieu         

                     of the capital letter 'A'.

 

 

 

b.xsd

<xs:simpleType>

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

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

<xs:pattern value="[a-z]{2}"/>

</xs:restriction>

</xs:simpleType>

 

b.xml

<?xml version="1.0"?>

<zzz aa="AB-5"/>

 

b.xml

<?xml version="1.0"?>

<zzz aa="ab"/>

 

Both xml files sail through smoothly since two pattern elements are provided to the simpleType. No limit has been stipulated for it. As a result, as many elements as deemed necessary can be provided to the restriction element. The first regular expression is maintained as before, whereas the second one, which is assigned to the second pattern, permits only two lower case characters.

 

Thus, we may assign the following to the attribute:

Two capital letters.

A minus sign.

A number or two lower case letters.

 

In the last case, any one of the two values is acceptable.

 

If the facet in the restriction is the same as above, then it would suffice even if one of them matches.

 

b.xsd

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

<xs:pattern value="[A-Z]{2}-[0-9]|[a-z]{2}"/>

</xs:restriction>

 

The above pattern element has the same effect as the earlier one. The OR sign | allows you to choose the way you would wish to place values in a single element.

 

You are rendered the flexibility of writing your pattern values either on a single line or spread over multiple lines. The only problem foreseen with the above approach is that if the 'space' character is used as a separator, then the xml file must also contain the same space. So, it is preferred not to include any spaces.

 

The | sign does not hold any significance for an enumeration. Thus, it cannot be used to separate the individual values of an enumeration. If we have multiple enumerator elements, they act like a logical OR.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa">

<xs:simpleType>

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

<xs:length value="2"/>

<xs:length value="2"/>

</xs:restriction>

</xs:simpleType>

</xs:attribute>

</xs:complexType>

</xs:element>

</xs:schema>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: This is a duplicate Length constraining facet. An error occurred at file:///c:/xmlprg/b.xsd(9, 2).

 

Facets such as the enumerator and the pattern cannot be repeated multiple times.

 

b.xsd

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

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

<xs:length value="2"/>

</xs:restriction>

 

The above xsd file generates an error, because barring the pattern and the enumeration, all the others follow the logical 'and'. All of them must necessary result in a value of 'true'.

 

In the above case, both the conditions have to be true, so that the overall result is also 'true'. However, logically this appears improbable. This is because, the first condition necessitates the presence of the 3 capital letters, while the second condition demands that the length should be 2. Both these conditions cannot be true simultaneously.

 

b.xsd

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

<xs:pattern value="[a-z]{2}"/>

<xs:enumeration value="bb"/>

<xs:enumeration value="cc"/>

</xs:restriction>

 

b.xml

<?xml version="1.0"?>

<zzz aa="bb"/>

 

An application of common sense is imperative while using the facets together. The above xml file works with the xsd file since only one of the enumerations from bb and cc is permitted. Also, since the pattern permits opting for any two small letters, both the conditions have been satisfied. Earnestly speaking, there really exists no requirement for the pattern.

 

Thus, the thumb rule is that you may have as many enumerators and patterns as you desire, but you need to be conservative in your use of other facets, since they are ANDed with each other.

 

The XML world is indifferent towards the logical consistency of your statements.

 

The simpleType elements are employed to extend or restrict an already existing built-in type. Similarly, complexTypes are pressed into action when elements are required. Both, attributes and content are handled in a similar manner by the simpleType as well as the complexType. There is no other Type element in the Schema world.

 

Different built-in types have diverse number of facets. The string type has six facets, viz. length, minLength, maxLength, pattern, enumeration and whitespace. The integer has eight facets, viz. totalDigits, maxInclusive, maxExclusive, minExclusive, minInclusive, pattern, whitespace and enumeration. The last three are common with the string type.  

 

Thus, the general guideline for dealing with the simpleType element is that, it is employed to restrict a built-in type or a simple type. It hires the different facets to do so. In the case of simple types, the attributes work in the manner similar to the one described earlier.

 

An element can be followed by either a simple type or a complex type.  The restriction element is used to restrict either the range of values or the number of occurrences.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa">

<xs:simpleType>

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

<xs:length value="3"/>

</xs:restriction>

</xs:simpleType>

</xs:attribute>

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz aa="ABC"/>

The length attribute determines the length of the value of the attribute. If the value entered is 3, then exactly 3 characters can be entered. Thus, aa="AB" produces an error. 

 

b.xsd

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

<xs:maxLength value="3"/>

</xs:restriction>

 

Alternatively, the maxLength facet determines the maximum number of characters that can be typed in. Therefore, in the above case, the count of the characters cannot exceed 3.

 

However, aa="ab" or aa="abc" shall not give out any error whatsoever. But, to assign a value of "abcd" would prove erroneous, since there are more than 3 characters.

 

Similarly, the minLength facet determines the minimum number of characters.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

 <xs:attribute name="aa" type="dd"/>

</xs:complexType>

</xs:element>

<xs:simpleType name="bb">

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

<xs:enumeration value="b1"/>

<xs:enumeration value="b2"/>

<xs:enumeration value="b3"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="cc">

<xs:list itemType="bb"/>

</xs:simpleType>

<xs:simpleType name="dd">

<xs:restriction base="cc">

<xs:length value="2"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz aa="b1 b2"/>

 

From here on, life takes a considerably complicated turn. Earlier, we had learnt about a simple list with multiple values. Then, we progressed on to an enumeration that rendered the option of choosing one out of the many values. The list did not impose any restriction on either the data used or the number of selected items.

 

The above program illustrates how multiple values can be chosen from a pre-ordained list. Also, it ensures that only a limited number of values are selected.

 

The values in the list are b1, b2 and b3, out of which any two could be selected. The value "b1 b2 b3" is not permitted, since in this case, all the three options have been selected. The value ''1 b4'' satisfies only one of the conditions, i.e. there must be two values present. However, b4 is an invalid value since it does not belong to the list.  The value of "b1 b2" meets all the requisite conditions. Hence, no errors are encountered.

 

Now, let us unearth as to how the xsd file implements the above complex condition.

 

The attribute aa is of type dd, which is a user-defined data type. Thus, the conditions placed on dd would determine what the user is allowed to key in as the value of the attribute aa. A type bb is created, which accepts only three values, viz. b1, b2 and b3, using the familiar enumeration element.

 

Then, the type cc is created, which accepts a list with the itemType as bb. Thus, cc can only accept the three values of b1, b2 and b3. Any element or attribute that is of type cc can use any of these three values. However, no restriction is imposed on their length.

Finally, another type, i.e. dd is created with the restriction element based on cc. The length facet is added to it, so that the number of occurrences is restricted to two. In a list, the length attribute corresponds to the number of individual items, and not to the actual length of its content.

 

To achieve this result, three different levels need to be implemented. Firstly, the number of possibilities is to be restricted. Secondly, the user key should be empowered to enter multiple values. Thirdly, the number of values that can be selected, should be restricted.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa" type="ee" />

</xs:complexType>

</xs:element>

<xs:simpleType name="bb">

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

<xs:maxInclusive value="100"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="cc">

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

<xs:enumeration value="b1"/>

<xs:enumeration value="b2"/>

<xs:enumeration value="b3"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="dd">

<xs:union memberTypes="bb cc" />

</xs:simpleType>

<xs:simpleType name="ee">

<xs:list itemType="dd" />

</xs:simpleType>

</xs:schema>

 

 

b.xml

<?xml version="1.0"?>

<zzz aa="b1 b2"/>

 

Since the attribute aa is of the data type ee, it would have the same constraints that govern ee. The type bb accepts numbers less than 100, while the type cc accepts the values b1, b2 or b3. The type dd is a union of bb and cc. Resultantly, the type dd can opt from the list of bb members and cc members.

 

Since the element ee can accept only one type, the element list is provided with a type dd, which obtains its members from the type bb and cc. This list element can then contain as many values as it desires, so long as it meets the constraint imposed by the type dd, i.e. the number should be less than 100, or it should be one of the following - b1, b2 and b3.

 

b.xml

<?xml version="1.0"?>

<zzz aa="b1 34 b2 b3 28 67"/>

 

b.xml

<?xml version="1.0"?>

<zzz aa="b1 67"/>

 

The abovementioned values of the attribute do not generate any error since the requisite condition has been met. The data must either follow the rules of type bb or of type cc.

 

b.xml

<?xml version="1.0"?>

<zzz aa="b1 67 789"/>

 

b.xml

<?xml version="1.0"?>

<zzz aa="b11 67 "/>

 

The above tosses an error at us. It is because, in the first case, the value 789 is not less than 100, while in the second case, the value b11 does not belong to the list of values of b1, b2 and b3.

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa" type="ff" />

</xs:complexType>

</xs:element>

<xs:simpleType name="bb">

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

<xs:maxInclusive value="100"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="cc">

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

<xs:enumeration value="b1"/>

<xs:enumeration value="b2"/>

<xs:enumeration value="b3"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="dd">

<xs:list itemType="bb" />

</xs:simpleType>

<xs:simpleType name="ee">

<xs:list itemType="cc" />

</xs:simpleType>

<xs:simpleType name="ff">

<xs:union memberTypes="dd ee" />

</xs:simpleType>

</xs:schema>

 

Using the XML schemas, the values that are incorporated within an element or an attribute, can be made extremely complex.

 

The above xsd file is a reverberation of the previous one, where the list is restricted to values contained exclusively in either the type bb or the type cc.

 

 

 

b.xml

<?xml version="1.0"?>

<zzz aa="b1 b2"/>

 

b.xml

<?xml version="1.0"?>

<zzz aa="1 2 30"/>

 

The xml files mentioned above, do not generate any error, even though multiple items originate from either the type bb or the type cc.

 

b.xml

<?xml version="1.0"?>

<zzz aa="1 2 30 b1"/>

 

Error

The 'aa' attribute has an invalid value according to its data type. An error occurred at file:///c:/xmlprg/b.xml(2, 6).

 

When the items are blended together, the above error is hurled at us.

 

In the xsd file, the attribute aa is of type ff. As before, the type bb can have a value less than 100, and the type cc can have the value b1 or b2 or b3. Now, the type dd is a list that derives from bb. Here, we may write as many numbers as deemed necessary, but each of them must be less than 100.

 

The type ee is also a list of type cc. Thus, any combination of the values b1, b2 and b3 can be entered.

 

Besides the two list types of dd and ee, another type called ff is created, which is a union of dd and ee. The union element authorizes selection from one of the two types.

 

The final outcome is that, an option exists for the attribute aa to choose from either the list of dd or ee. Without the union, the list would have had to be selected from either bb or cc. As per the option available, only one out of these can be selected at a time, and not both. Duplicate values are also permissible in a list.

 

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:union>

<xs:simpleType>

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

<xs:enumeration value="g1"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType>

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

<xs:enumeration value="g2"/>

<xs:enumeration value="g3"/>

</xs:restriction>

</xs:simpleType>

</xs:union>

</xs:simpleType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa>g2</aaa>

</zzz>

 

A union is merely a collection of types. Apart from using the approach witnessed above for creating a union, there is yet another alternative that could be resorted to. This is showcased in the above xsd file. A simple type c1 starts with the union element, which in turn is constituted of a number of anonymous simpleType elements.

 

Each of these simpleType elements uses enumeration to restrict the string type used as base. The only flipside of the above method is that the simple types are incapable of being reused.

 

By now, you must have realized that the maxOccurs attribute takes either a value of 'unbounded' or that of a positive integer. The only way of implementing this attribute is by using a union. This has been demonstrated below.

 

b.xsd

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="maxOccurs1" type="c1" default="1"/>

</xs:complexType>

</xs:element>

<xs:simpleType name="c1">

<xs:union memberTypes="c2 xs:nonNegativeInteger"/>

</xs:simpleType>

<xs:simpleType name="c2">

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

<xs:enumeration value="unbounded"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz maxOccurs1="unbounded" /> 

 

b.xml

<?xml version="1.0"?>

<zzz maxOccurs1="5" /> 

 

A simpleType c2 is created by deriving from the string type. However, by using enumeration, its value is limited to a single value, i.e. 'unbounded'. So, the simple type c1 is provided a single union element, which takes a value from the following two types: The type c2 and the built-in type nonNegativeInteger.

 

Thus, in the xml file, the attribute maxOccurs1 can now assume either the value of 'unbounded' (similar to the first case), or a positive integer (like in the second case).

 

If no value has been specified, it assumes the default value of 1, since this the value of the default 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:simpleType name="c3">

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

<xs:maxInclusive value="50"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="c2">

<xs:list itemType="c3"/>

</xs:simpleType>

<xs:simpleType name="c1">

<xs:restriction base="c2">

<xs:length value="3"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa>12 34 44</aaa>

</zzz>

 

The rules imposed on the attributes do not change with the elements. What is required is a series of numbers in the form of a list, as the content of element aaa. However, there is a ceiling placed on the number of items that can be present in the list, which is three. Moreover, the numbers must be smaller in value than 50.

 

The most optimum way of working on programs is by building error-checks in it, one at a time.

 

Therefore, we start by creating a simple type c3, which restricts the type positiveInteger to a value less than 50, using the maxInclusive attribute. Thus, any entity whose type is c3, must have a positive integer of less than 50. Then, one more simple type c2 is created, which uses this type c3 as part of the list item. Thus, the type c2 can have innumerable positive numbers, provided they are less than 50.

 

The third condition was that the length should be 3. To achieve this, a new type c1 is derived from c2 with the facet length. Thus, by deriving new types, the existing type can be tailored to suit our needs. Finally, this type is used to restrict the content that can be carried by the element aaa.

 

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="c3">

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

<xs:maxInclusive value="50"/>

</xs:restriction>

</xs:simpleType>

<xs:simpleType name="c1">

<xs:restriction>

<xs:simpleType>

<xs:list itemType="c3" />

</xs:simpleType>

<xs:length value="3"/>

</xs:restriction>

</xs:simpleType>

</xs:schema>

 

The old adage that there are many ways to skin a cat, is very germane to this case too. The above xsd program achieves the same result as the previous program, albeit in a slightly different manner. The simple type c3 restricts the value of a positive number to less than 50, the type c2 is skipped and then, the type c1 is created.

 

The 'restriction' element introduces an anonymous simpleType that has a list initialized to type c3. After closing the simple type, the 'length' facet is introduced, which confines the use of numbers to 3. This has been implemented so that the base and child simpleType cannot be used simultaneously.

 

Now, carry out a few changes. Add a simpleType c2 at the end of the xsd file and then, alter the restriction element in simpleType c1 to the base of c2.

 

<xs:simpleType name="c1">

<xs:restriction base="c2">

 

<xs:simpleType name="c2">

<xs:restriction>

<xs:simpleType>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Either the base attribute or the simpleType child must be present, but not both. An error occurred at file:///c:/xmlprg/b.xsd(20, 2).

 

The error message provides ample evidence of the fact that the base attribute and a simpleType child cannot have the same values concurrently.

 

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="c3" />

<xs:simpleType name="c2">

<xs:list itemType="c3"/>

</xs:simpleType>

</xs:schema>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Type 'c3' is not declared or not a simple type. An error occurred at file:///c:/xmlprg/b.xsd(10, 2).

 

In this program, c3 is made as a complexType instead of a simple Type, and it is used in the list of types provided to the itemType attribute of the list element. The exception is thrown since C# scans the list of types and seeks only the simple types or the built-in types, since they are the ones that qualify to be specified as types.

 

It is an exercise in futility to specify a complex Type, since complex types possess much more information than mere values, as they are capable of containing elements too.

 

The following program solves the problem of representing elements as values of a list.

 

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="c3">

<xs:list itemType="xs:integer"/>

</xs:simpleType>

<xs:simpleType name="c2">

<xs:list itemType="c3"/>

</xs:simpleType>

</xs:schema>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: A list data type must be derived from an atomic or union data type. An error occurred at file:///c:/xmlprg/b.xsd(12, 2).

 

In the above program, we create a simpleType c3 that contains a list of integers. No problems are faced here. Then, a simpleType c2 is created, which holds a list of type c3.

 

However, an exception gets generated because c3 is already a list, and by no means can we specify a list of lists. The concept of a list of lists cannot be implemented in a clear-cut manner, since it has myriad dimensions to it.

 

The list can only contain 5 facets. The facet of 'length', as we had learnt earlier, specifies the number of items that the list can have in the xml file. This makes the list very restrictive. Therefore, minLength and maxLength are used to specify the minimum and maximum length of the list, respectively. This is followed by the familiar enumeration and pattern, which have already been discussed earlier.

 

b.xsd

<?xml version="1.0" encoding="utf-8"?>

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

<xs:element name="zzz">

<xs:complexType>

<xs:attribute name="aa" type="ff" />

</xs:complexType>

</xs:element>

<xs:simpleType name="bb">

<xs:restriction base="cc" />

</xs:simpleType>

<xs:simpleType name="cc">

<xs:restriction base="bb" />

</xs:simpleType>

</xs:schema>

 

Error

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Circular type reference. An error occurred at file:///c:/xmlprg/b.xsd(8, 2).

 

The XML Validator can never be caught napping on duty! The exception thrown above establishes this fact. Here, bb is a simple type, which is made up of type cc. The glitch is that when the type cc is created, it is based on the type bb. This creates a circular reference, resulting in the above error.

 

As an aside, had we used a restriction of the length facet above, we could have also ensured that the user only entered a specific number of values, ranging between a minimum and maximum number of values.

 

b.xsd

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

<xs:element name = "zzz">

<xs:complexType>

<xs:sequence minOccurs="0" maxOccurs="unbounded">

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

</xs:sequence>

<xs:attribute name="aa" type="xs:string" />

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz aa="hi">

<aaa> 123 </aaa>

</zzz>

 

We should have introduced the above program eons ago. This one exhibits the root element zzz with a tag aaa and an attribute called aa. This is permissible since the attribute element cannot be placed outside the complexType, as it belongs to the element called zzz. So far, the attribute and the element have not been assigned the same name in the xsd file.

 

Exploiting our next surge of creativity, we would like to associate the attribute aa with the element aaa, and not with zzz. Thus, the tag aaa should be written as: <aaa aa="no" > 123 </aaa>

 

It is very easy to create an element aaa that contains a decimal number or an integer as follows:

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

 

As per our requirement, now an attribute has to be added to this element aaa. However, simple built-in types cannot have attributes. Only the complex types have the privilege of possessing them.

 

Thus, since the type decimal is a simple built-in type, it cannot acquire attributes. The only workable solution to this poser is to have a complexType definition, where the element aaa can be created or placed with the attribute of aa. As a consequence, the complex type is created, which derives from or is based upon the simple type decimal.

 

b.xsd

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

<xs:element name = "zzz">

<xs:complexType>

<xs:sequence minOccurs="0" maxOccurs="unbounded">

<xs:element name="aaa">

<xs:complexType>

<xs:simpleContent>

<xs:extension base="xs:decimal">

<xs:attribute name="aa" type="xs:string"/>

</xs:extension>

</xs:simpleContent>

</xs:complexType>

</xs:element>

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

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa aa="hi" > 123 </aaa>

<bbb> bye </bbb>

</zzz>

 

As always, the root tag zzz is followed by an anonymous type definition, which embodies all the contents. The sequence element is used to place the various elements contained within the type in a specific sequence. Presently, there are only two elements, out of which, aaa is an open tag and the other one named bbb is a single tag. The element aa defines an anonymous complexType type.

 

Upto this point, the complexType element has had one of the following: a choice, a sequence, an element and an attribute. Here, we use the element simpleContent to signify that the new type has no elements, but only character data. Since the type is employed to extend the simple decimal-type, the 'extension' element is used.

 

The base attribute specifies the type that is being extended. Thus, it indicates the data type of the content. In addition to this, the attribute element is also specified, so that the aaa element can be extended with these attributes. The element can extend numerous attribute elements and incorporate all the finer aspects learnt here. The base attribute determines the data type of the content of the element aaa.

 

In the case of elements, we can have sub-elements within sub-elements. All of them can contain character data, which can be enveloped within the deepest sub-elements too.

 

The next program is an enhancement over the previous one. Here, the root element zzz carries the element aaa, which in turn, carries an element bbb. You may possibly wonder as to what is the big deal, since we already have considerable experience in handling such child elements. The innovative twist here is that we now want to place some content between these tags.

 

b.xsd

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

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa">

<xs:complexType mixed="true">

<xs:sequence>

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

</xs:sequence>

</xs:complexType>

</xs:element>

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

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa>  hi

<bbb> bye </bbb>

yes

</aaa>

<ccc> no </ccc>

</zzz>

 

As before, the root element zzz is provided with a complexType element to hold all the bits and pieces.

 

Then, the two elements of aaa and ccc are placed in a sequence. Since there are no attributes that qualify this sequence, these elements must be placed one after the other. To enable the aaa element to hold a bbb element, a complexType element has to be specified.

 

 

The element bbb is also placed in a sequence. Even though this sequence element accomplishes nothing, it must be specified, because a complexType has to be followed by something other than an element.

 

After all the element tags have been closed, we converge all our attention to the complexType for the aaa element, where the key attribute is defined. The mixed attribute expressly authorizes the content to be mixed.

 

Thus, the character data can now appear between child elements. Therefore, words such as 'hi' can now be specified between the aaa tag and its child bbb.

 

The default value is 'false'. Thus, removing the mixed=true attribute from the complex type element leads to the following exception. :

 

Error

Element 'aaa' has invalid child element '#PCDATA'. Expected 'bbb'. An error occurred at file:///c:/xmlprg/b.xml(3, 6).

 

b.xml

<ccc> no </ccc>

bad

</zzz>

 

Adding 'bad' at the end of the xml file will yield the same error, since the mixed attribute of the first complexType is set to 'false' by default. If we now change it to mixed="true", the error vamooses. The mixed attribute is not inheritable by the inner complexType elements. Thus, on removing the inner mixed="true" and retaining the outer one, an exception is thrown, which is attributed to the presence of the character data 'hi' within the element aaa.

 

The mixed model of the XML Schema world is fundamentally different from the mixed model seen in XML 1.0. The XML Schema world is very stringent about the sequence and the number of child elements appearing in either the xml file or the instance document.

 

 

However, this does not hold true of the older world of xml 1.0, where no rules are enforced on either the sequence or the number of child elements present in the instance document.

 

Thus, XML Schemas have comprehensive error checks unlike xml 1.0, which gives us lot of leeway.

 

b.xsd

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

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa">

<xs:complexType>

<xs:attribute name="a1" type="xs:string"/>

<xs:attribute name="a2" type="xs:string"/>

</xs:complexType>

</xs:element>

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa a1="hi" a2="bye" />

</zzz>

 

The above xsd creates an element aaa within the root. It takes two attributes, viz. a1 and a2, but without any content.

 

b.xml

<?xml version="1.0"?>

<zzz>

<aaa a1="hi" a2="bye">

hi

</aaa>

</zzz>

 

Error

Element cannot contain text or whitespace. Content model is empty. An error occurred at file:///c:/xmlprg/b.xml(3, 23).

 

Addition of character data between the element results in the above exception.

 

The element aaa has a complex type with merely two attributes, but without any elements. There can be no sequence after the complexType, since an order cannot be imposed on attributes.

 

It is not evident from the above, whether we are empowered to have any content between the elements aaa or not. Let us attempt an innovative approach for creating an element wherein no content is allowed.

 

b.xsd

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

<xs:element name="zzz">

<xs:complexType>

<xs:sequence>

<xs:element name="aaa">

<xs:complexType>

<xs:complexContent>

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

<xs:attribute name="a1" type="xs:string"/>

<xs:attribute name="a2" type="xs:string"/>

</xs:restriction>

</xs:complexContent>

</xs:complexType>

</xs:element>

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>

 

The xml file remains unaltered.

The xsd file commences with the attributes elements immediately after the complexType, but now, with the element of complexContent. This element can contain either extensions or restrictions, and it is used on a complexType, which only contains mixed content or elements. It can either contain a single restriction or a single extension.

 

The restriction element restricts the contents of the complex type to a subset of what is permissible. The base type anyType shall be explained in the forthcoming chapters. The complexContent element is one way of restricting or extending the content model of the complex type that is being declared. No element content is introduced. Merely two attributes are provided.

 

It is entirely upto the user to select between the following two methods: Either have a complexType element without any simpleContent, or have a complexContent element, which is another way of acquiring an element withs no content.