XML Tutorial
Volume 6 : XML Schema Data Types (Part II)
Seiichi Kinugasa
Index
Extending Complex Types
Complex Type Restrictions
Method to Reuse a Type in Practice
Review Questions
Extending Complex Types
Complex type extensions are quite similar to the inherit function of Java, C++ and other object-oriented languages. New element declarations and attribute declarations can be added to the base complex type data type. The difference is that the additional element is added to the end of the base data type, and when the complex type is extended, the data type becomes a complex type.
As with the previous volume, this concept may be too difficult to communicate in words alone. Accordingly, let's take a look at the following example to consider how complex type extensions are defined.
- [1] The Name element and Department element are string types; an complex type EmpType type will be created, resulting in the occurrence of the Name element and Department element in that order.
- [2] Based on the EmpType type, we will create an extended type (ExtEmpType) to which the string type Telephone element and int type Employee_Number attribute (required) will be added.
Definition Method for [1]
First, we will use the "complexType element" to define the complex type, designating "EmpType" as the name attribute.
<xs:complexType name="EmpType">
:
</xs:complexType>
Next, we will define the order of occurrence for the child elements. To output the elements in Name element ? Department element order, we will use the "sequence element." For the child element declaration, we designate the ref attribute of the "element element," and provide a definition to reference an element declaration declared in a separate location.
<xs:sequence>
<xs:element ref="Name" />
<xs:element ref="Department" />
</xs:sequence>
Last, we make the element declaration:
<xs:element name="Name" type="xs:string" />
<xs:element name="Department" type="xs:string" />
The final EmpType type will look like LIST 1:
LIST1: EmpType Type Example
<xs:complexType name="EmpType">
<xs:sequence>
<xs:element ref="Name" />
<xs:element ref="Department" />
</xs:sequence>
</xs:complexType>
<xs:element name="Name" type="xs:string" />
<xs:element name="Department" type="xs:string" />
Definition Method for [2]
Since we will be adding the Telephone element and Employee_Number attribute on the EmpType type complex type base, the result will be a complex type extension.
First, we use the complexType element, and designate the ExtEmpType with the name attribute.
<xs:complexType name="ExtEmpType">
:
</xs:complexType>
Next, we designate the "complexContent element," defining the content of the child element of the complexType element as a complex type.
<xs:complexContent>
:
</xs:complexContent>
Next, we will describe the "extension element" representing the extension, and use the base attribute to designate the data type serving as the base. In this example, we will designate "EmpType" in the base attribute.
<xs:extension base="EmpType">
:
</xs:extension>
Last, we will define the Telephone element and Employee_Number attribute to be added. When defining the attribute, we must do so after the definitions of the sequence element, choice element or other child elements (model group).
<xs:extension base="EmpType">
<xs:sequence>
<xs:element ref="Telephone" />
</xs:sequence>
<xs:attribute name="Employee_Number" type="xs:int" use="required" />
</xs:extension>
:
<xs:element name="Telephone" type="xs:string" />
The final ExtEmpType type will look like the following:
The declaration of the ExtEmpType type Employee element is as follows:
<xs:element name="Employee" type="ExtEmpType" />
Under complex type extensions, the added declaration will occur at the end. Accordingly, the child elements of the Employee element must be described in order: Name element, Department element, Telephone element. The following shows examples of a valid XML document and invalid XML documents for this definition.
●Valid XML Document
〈Name〉Masashi Okamura〈/Name〉
〈Department〉Design Department〈/Department〉
〈Telephone〉03-1452-4567〈/Telephone〉
〈/Employee〉
●Invalid XML Document
(Name, Department, and Telephone elements are not described in that order)
〈Name〉Aiko Tanaka〈/Name〉
〈Telephone〉03-6459-9864〈/Telephone〉
〈Department〉Sales Department〈/Department〉
〈/Employee〉
●Invalid XML Document
(Employee_Number attribute is not described)
〈Name〉Takashi Kagawa〈/Name〉
〈Department〉Human Resources Department〈/Department〉
〈Telephone〉07-5432-9876〈/Telephone〉
〈/Employee〉
Complex Type Restrictions
New data types can be created from complex types by adding restrictions such as those shown below. When restricting a complex type, that data type becomes a complex type.
- Change (restrict) the number of occurrences of an element
- Narrow the range of the simple type value used for an element or attribute
- Change (restrict) the occurrence constraints for an attribute
Here as well, we will look at the following example:
[1] Create the following complex type UserType type
- The string type Name, Telephone, and Email elements occur in that order
- The Name and Email elements occur once each; the Telephone element may occur between one and three times
- A date type Updated_Date attribute is provided (may be omitted)
[2] The following SimpleUserType type will be created for the UserType type with the following constraints:
- The Telephone element may occur only once
- The Updated_Date attribute description is mandatory
Definition Method for [1]
As with the complex type definition discussed above, we will use the complexType element and sequence element to create the UserType type. The number of occurrences will be defined using the "minOccurs attribute" and "maxOccurs attribute" of the element element. Since the default value of both attributes is "1," they can be omitted when the number of occurrences is 1. However, in this example, the number of occurrences for the Telephone element can be between one and three, so "3" will be input for the maxOccurs attribute.
The completed UserType type looks like LIST 2 below:
LIST2: UserType Type Example
<xs:complexType name="UserType">
<xs:sequence>
<xs:element ref="Name" />
<xs:element ref="Telephone" maxOccurs="3"/>
<xs:element ref="Email" />
</xs:sequence>
<xs:attribute name="Updated_Date" type="xs:date" use="optional" />
</xs:complexType>
<xs:element name="Name" type="xs:string" />
<xs:element name="Telephone" type="xs:string" />
<xs:element name="Email" type="xs:string" />
[2] Create a SimpleUserType type by adding constraints to the UserType type
In Example [2], we will add a restriction on the number of occurrences for the Telephone element of the UserType type complex type, and change the occurrence constraints of the Updated_Date attribute.
First, we will use the complexType element, and designate the SimpleUserType with the name attribute.
<xs:complexType
name="SimpleUserType">
:
</xs:complexType>
Next, we will designate the complexContent element to define the content of the child element of the complexType element as a complex type.
<xs:complexContent>
:
</xs:complexContent>
Next, we will describe the "restriction element" representing the restriction, and designate the data type serving as the base using the base attribute.
<xs:restriction base="UserType">
:
</xs:restriction>
Last, we will describe all of the definitions for the content of the data type serving as the base, describing the restricted content as follows:
- When restricting the number of occurrences of an element, use the maxOccurs or minOccurs attributes.
- When changing the description of an attribute to mandatory input, change the use attribute to "required."
The completed SimpleUserType type is as follows:
The following is the SimpleUserType type User_Information element declaration.
<xs:element name="User_Information" type="SimpleUserType" />
As a result, examples of a valid XML document and invalid XML documents for this XML Schema document are shown below:
●Valid XML Document
〈Name〉Ichiro Yamamoto〈/Name〉
〈Telephone〉03-1452-4567〈/Telephone〉
〈Email〉yama@abc.gr.jp〈/Email〉
〈/User_Information〉
●Invalid XML Document
(Multiple Telephone elements are described)
〈Name〉Akihiko Takeda〈/Name〉
〈Telephone〉03-1452-4567〈/Telephone〉
〈Telephone〉06-5412-7654〈/Telephone〉
〈Email〉takeda@abc.gr.jp〈/Email〉
〈/User_Information〉
●Invalid XML Document
(Updated_Date attribute is not described)
〈Name〉Mika Aoki〈/Name〉
〈Telephone〉03-9976-9876〈/Telephone〉
〈Email〉mika@abc.gr.jp〈/Email〉
〈/User_Information〉
Method to Reuse a Type in Practice
In both this and the prior volume, we have discussed methods to reuse simple types and complex types. In practice, reusing a type often consists of saving the type designated as the base in a separate file, referencing the file using <xs:include> or <xs:import>, and then creating a new type.
- <xs:include>: Load an XML Schema file having the same namespace or no namespace
- <xs:import>: Load an XML Schema file having a different namespace
Using this method, a frequently used custom data type is saved in a separate file as an external schema, allowing for the description of schema with superior maintainability.
The following is an example of the practical usage of <xs:include>:
You can also use <xs:import> to load industry standard XML Schema files used in a variety of industries (in this case, the namespace is different).
Review Questions
Question 1
Select two of the following that represent valid XML documents with respect to the XML Schema document below:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Customer_Information" type="CustomerType" />
<xs:complexType name="InfoType">
<xs:sequence>
<xs:choice>
<xs:sequence>
<xs:element ref="Company" />
<xs:element ref="Address" />
</xs:sequence>
<xs:sequence>
<xs:element ref="LastName" />
<xs:element ref="FirstName" />
</xs:sequence>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="CustomerType">
<xs:complexContent>
<xs:extension base="InfoType">
<xs:choice>
<xs:element ref="Telephone" />
<xs:element ref="Mobile" />
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="Company" type="xs:string" />
<xs:element name="Address" type="xs:string" />
<xs:element name="LastName" type="xs:string" />
<xs:element name="FirstName" type="xs:string" />
<xs:element name="Telephone" type="xs:string" />
<xs:element name="Mobile" type="xs:string" />
</xs:schema>
- <Customer_Information>
<Company>masashi</Company>
<Address>okamura</Address>
<Mobile>090-9231-3678</Mobile>
<Mobile>090-6345-6989</Mobile>
</Customer_Information> - <?xml version="1.0" ?>
<Customer_Information>
<Company>masashi</Company>
<Address>okamura</Address>
<Mobile>090-9231-3678</Mobile>
</Customer_Information> - <?xml version="1.0" ?>
<Customer_Information>
<Company>Okamura</Company>
<Address>Masashi</Address>
<Telephone>03-0001-6789</Telephone>
</Customer_Information> - <?xml version="1.0" ?>
<Customer_Information>
<Company>Okamura</Company>
<Address>Masashi</Address>
<LastName>masashi</LastName>
<FirstName>okamura</FirstName>
<Telephone>03-0001-6789</Telephone>
<Mobile>090-9231-3678</Mobile>
</Customer_Information>
Comments
This question deals with a complex type extension. Looking at the XML Schema document designated in this problem, the definitions below can be inferred:
- The root element is the Customer_Information element
- The Company element and Address element occur in that order
- The LastName element and FirstName element occur in that order
- Either the combination of the Last Name element and the Address element, or the combination of the LastName element and the FirstName element occurs
- Either the Telephone element or the Mobile element occurs one time
Accordingly, only the XML document that meets the conditions above is a valid XML document. In A, the "Mobile" element occurs two times, so this is not a valid XML document. Both B and C fulfill the conditions, and are therefore valid XML documents. In answer D, all of the elements defined within the XML Schema document occur, so this is not a valid XML document. Accordingly, the correct answer is B and C.
Question 2
Select which of the following correctly represents what should be described in (1) of the XML Schema document in order to correctly define the following XML Document (the Location_of_Origin attribute of Fruit element is mandatory):
[XML Document]
<?xml version="1.0" ?>
<Fruit Location_of_Origin="Aomori">
<Name>Apple</Name>
<Price>350</Price>
</Fruit>
[XML Schema Document]
<?xml version="1.0" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Fruit" type="fruitType" />
<xs:complexType name="baseType">
<xs:sequence>
<xs:element ref="Name" />
</xs:sequence>
</xs:complexType>
<xs:element name="Name" type="xs:string" />
<xs:element name="Price" type="xs:integer" />
</xs:schema>
- <xs:complexType name="fruitType">
<xs:complexContent>
<xs:restriction base="baseType">
<xs:sequence>
<xs:element ref="Price" />
</xs:sequence>
<xs:attribute name="Location_of_Origin"
type="xs:string" use="required" />
</xs:restriction>
</xs:complexContent>
</xs:complexType> - <xs:complexType name="fruitType">
<xs:complexContent>
<xs:extension base="baseType">
<xs:sequence>
<xs:element ref="Price" />
</xs:sequence>
<xs:attribute name="Location_of_Origin"
type="xs:string" use="required" />
</xs:extension>
</xs:complexContent>
</xs:complexType> - <xs:complexType name="fruitType">
<xs:simpleContent>
<xs:extension base="baseType">
<xs:sequence>
<xs:element ref="Price" />
</xs:sequence>
<xs:attribute name="Location_of_Origin"
type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
- <xs:complexType name="fruitType">
<xs:simpleContent>
<xs:restriction base="baseType">
<xs:sequence>
<xs:element ref="Price" />
</xs:sequence>
<xs:attribute name="Location_of_Origin"
type="xs:string" use="required" />
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
Comments
The XML Document contains a Fruit element having a Location_of_Origin attribute, and a Name element and Price element as child elements of the Fruit element. For the XML Schema Document, the Fruit element is a fruitType type, defined as a baseType type having only a Name element.
Accordingly, to derive the answer to this question, all one needs to do is define the fruitType type to which the string type Price element and Location_of_Origin attribute have been added, based on the baseType type. The complex type extension syntax is as follows:
<xs:complexType name="New Type">
<xs:complexContent>
<xs:extension base="Base Type">
Designate the Model Group
Designate the Attribute
</xs:extension>
</xs:complexContent>
</xs:complexType>
Let's look at each choice based on this syntax. Answer A defines the content as a complex type using the complexContent element, and the restriction element defines the complex type restriction, meaning that this answer is incorrect. Originally, the baseType attribute has no Location_of_Origin attribute, which will cause an error during validation. Answer B defines the content as a complex type using the complexContent element, and defines the complex type extension for the extension element. Accordingly, this answer is correct. Answers C and D define the content as a simple type using the simpleContent element, and are therefore incorrect.
Accordingly, the correct answer is B.
Seiichi Kinugasa
Hewlett-Packard Japan HP Training Services.
I currently oversee XML training courses as an Infoteria-certified trainer, providing technical and training support for IT professional development programs, including large-scale Web development support courses. Not having been asked to write magazine articles for quite some time, I am truly feeling the pressure, but I will continue to give my best for the next two articles I am writing for this series.
The content presented here is an HTML version of an article that originally appeared in the August 2007 issue of DB Magazine published by Shoeisya.