XML

 


COIN78 - XML Lesson 6: XSD Schema and XML


Section 1: What is an XML Schema?

  1. Defines elements that can appear in a document
  2. Defines attributes that can appear in a document
  3. Defines which elements are child elements
  4. Defines the sequence in which the child elements can appear
  5. Defines the number of child elements
  6. Defines whether an element is empty or can include text
  7. Defines data types for elements and attributes
  8. Defines default and fixed values for elements and attributes

The purpose of a Schema is to define the legal building blocks of an XML document, just like a DTD.

BUT....

XML Schemas will be used in Web applications as a replacement for DTDs. Here are the reasons why:

  1. XML Schemas are easier to learn than DTD
  2. XML Schemas are extensible to future additions
  3. XML Schemas are richer and more useful than DTDs
  4. XML Schemas are written in XML
  5. XML Schemas support data types
  6. XML Schemas support namespaces

Sample files:

We will be working with a number of sample files. You should open shippingOrder_xsd.xml and shippingOrder.xsd . If you have problems viewing the shippingOrder.xsd document, try opening shippingOrder.xml, which is the schema, shippingOrder.xsd, but has xml as the filetype so that you can view it directly in the browser. These are valid XML files, so IE 5.5 should be able to render them. A file which contains a reference to these schema (without data) is shipOrder.xml. The following is shippingOrder_xsd.xml:

<?xml version="1.0" encoding="UTF-8"?>
<shippingOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="shippingOrder.xsd">
	<shipTo>
		<name>Tove Svendson</name>
		<street>Ragnhildvei 2</street>
		<address>4000 Stavanger</address>
		<country>Norway</country>
	</shipTo>
	<items>
		<item>
			<title>Empire Burlesque</title>
			<quantity>1</quantity>
			<price>10.90</price>
		</item>
		<item>
			<title>Hide your heart</title>
			<quantity>1</quantity>
			<price>9.90</price>
		</item>
	</items>
</shippingOrder>

The following is the schema, shippingOrder.xsd.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<xsd:element name="shippingOrder" type="shippingOrderType"/>
	<xsd:complexType name="shippingOrderType">
		<xsd:sequence>
			<xsd:element name="shipTo" type="shipToType"/>
			<xsd:element name="items" type="itemsType"/>
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="shipToType">
		<xsd:sequence>
			<xsd:element name="name" type="xsd:string"/>
			<xsd:element name="street" type="xsd:string"/>
			<xsd:element name="address" type="xsd:string"/>
			<xsd:element name="country" type="xsd:string"/>
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="itemsType">
		<xsd:sequence>
			<xsd:element name="item" type="itemType" maxOccurs="unbounded"/>
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="itemType">
		<xsd:sequence>
			<xsd:element name="title" type="xsd:string"/>
			<xsd:element name="quantity" type="xsd:positiveInteger"/>
			<xsd:element name="price" type="xsd:decimal"/>
		</xsd:sequence>
	</xsd:complexType>
</xsd:schema>

We will be creating a schema document for our address book, address_book.xml shown in address_schema.xml and address_schema.xsd. These can serve as a working reference for your eventual project files.

Section 2: Beginning a Schema

  1. Indicating a schema's location - Open shippingOrder.xsd (or open shippingOrder.xml if you have problems). Since an XML schema is an XML document, we begin the schema with a processing instruction that is the prolog of the XML document. The root element is <xsd:schema>, which includes the namespace. The example above shows the contents of the shippingOrder.xsd schema file. Below is shipOrder.xml which shows the reference to shippingOrder.xsd.

    <?xml version="1.0" encoding="UTF-8"?>
    <shipOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="shippingOrder.xsd"
    > <shipTo> <name/> <street/> <address/> <country/> </shipTo> <items> <item> <title/> <quantity/> <price/> </item> <item> <title/> <quantity/> <price/> </item> </items> </shipOrder>

  2. Declaring a namespace - Open address_schema_1.xml to see the namespace declaration. We'll talk more about namespaces next week, but namespaces hold archives of "global" elements and declarations. The file shipOrder.xml contains a reference to the namespace and the schema file which is shown in the previous example.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    	<xsd:annotation>
    		<xsd:documentation>This schema will be used for our address_book.xml document
    		</xsd:documentation>
    	</xsd:annotation>
    
    	<xsd:element name="address_book" type="addressBookType"/>
    
    </xsd:schema>

  3. Annotating a schema - It's a good idea to annotate a schema, especially if it refers to another schema, or is a "work in progress". Open address_schema_1.xml to see my annotation.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    	<xsd:annotation>
    		<xsd:documentation>This schema will be used for our address_book.xml document
    		</xsd:documentation>
    	</xsd:annotation>
    
    	<xsd:element name="address_book" type="addressBookType"/>
    
    </xsd:schema>

Section 3: Simple Types

  1. Declare an element with a simple type - The riddle of schema is that simple types aren't so simple, and complex types aren't so complex. Simple types can contain only text. Additionally, XML schema has built in simple types for most kinds of text. These include string, decimal, Boolean, date, time, uri-reference, language, or "custom". Custom is the name of a custom simple type that you invent for your schema.
  2. xsd:schema - <xsd:schema is the root element of the .xsd document. In it you will declare the location of the namespace by which your schema document is validated.
  3. xsd:element - <xsd:element is where you will declare the "name" of the root element that the schema is applied to in the xml document, and the "type". Open address_schema_3.xml to see "name" and "type".

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
        <!-- 
           The element name "address_book speaks to the root element of the XML document"
           The type "addressBookType" will be defined as a complex element in the next part 
        -->
    
        <xsd:element name="address_book" type="addressBookType"/>
    
    </xsd:schema>

  4. xsd:complexType - This is where the fun begins. A complex type will typically contain elements, elements and text, attributes, and combinations of all the above. In address_schema_4.xml we start to build out the address_book element declarations.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    	<!-- The type "addressBookType" will be defined as a complexType -->
    	<xsd:element name="address_book" type="addressBookType"/>
    
    <!-- addressBookType contains the element "record" which isunbounded in occurance --> <xsd:complexType name="addressBookType"> <xsd:sequence> <xsd:element name="record" type="recordType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:schema>

    Next, we will look at an anonymous type. It is anonymous because there is no type name in the outermost element and the inner element is directly nested. This means that the nested element cannot be used by other elements in the schema. If it were a named type, like the one in the example just above, then it could be included by other elements in the schema. Open anonComplex.xml and anonComplex.xsd (anonComplex_xsd.xml).

    <?xml version="1.0"?>
    
    <!-- This code will be used to define the element sibling, which contains an 
         anonymous element -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="siblings">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="sibling" type="xsd:string"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>

  5. xsd:sequence - Sequence will contain the elements that nest, or reside within an outer element. Each complexType will have a name that will be used to declare all the elements that it includes. Open address_schema_5.xml we start to build out the sequences.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <!-- The type "addressBookType" will be defined as a complexType --> <xsd:element name="address_book" type="addressBookType"/> <!-- addressBookType contains the element "record" which is unbounded in occurance --> <xsd:complexType name="addressBookType"> <xsd:sequence> <xsd:element name="record" type="recordType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <!-- recordType contains the elements "name", "address", and "contact" --> <!-- we use xsd:sequence to declare the order in which they will appear --> <xsd:complexType name="recordType"> <xsd:sequence> <xsd:element name="name" type="nameType"/> <xsd:element name="address" type="addressType"/> <xsd:element name="contact" type="contactType"/> </xsd:sequence> </xsd:complexType> </xsd:schema>

  6. complexTypes and complexContent - After we have declared the sequence of elements for the "record" element, we need to declare and create sequences for "name", "address" and "contact" elements. Each of these will in turn contain elements, and possibly attributes as well. Open address_schema_6.xml, address_schema_7.xml, and address_schema_8.xml to see each of these.
    This snippet contains the all of the complexType(s) for the address_schema example which is address_schema_8.xml.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <!-- The type "addressBookType" will be defined as a complexType --> <xsd:element name="address_book" type="addressBookType"/> <!-- addressBookType contains the element "record" which is unbounded in occurance --> <xsd:complexType name="addressBookType"> <xsd:sequence> <xsd:element name="record" type="recordType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <!-- recordType contains the elements "name", "address", and "contact" --> <!-- we use xsd:sequence to declare the order in which they will appear --> <xsd:complexType name="recordType"> <xsd:sequence> <xsd:element name="name" type="nameType"/> <xsd:element name="address" type="addressType"/> <xsd:element name="contact" type="contactType"/> </xsd:sequence> </xsd:complexType> <!-- nameType conatins the elements "first_name", "middle_name", "last_name", and "nick_name" --> <!-- each of these elements is type "xsd:string" --> <xsd:complexType name="nameType"> <xsd:sequence> <xsd:element name="first_name" type="xsd:string"/> <xsd:element name="middle_name" type="xsd:string"/> <xsd:element name="last_name" type="xsd:string"/> <xsd:element name="nick_name" type="xsd:string"/> </xsd:sequence> </xsd:complexType>

    <!-- addressType conatins the elements "street_address", "street_address_detail", "city", "state", and "zipcode" --> <!-- each of these elements is type "xsd:string" --> <xsd:complexType name="addressType"> <xsd:sequence> <xsd:element name="street_address" type="xsd:string"/> <xsd:element name="street_address_detail" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zipcode" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <!-- complexType conatins the elements "home_phone", "work_phone", "cell_phone", "fax_number", and "email_address" --> <!-- each of these elements is type "xsd:string" --> <xsd:complexType name="contactType"> <xsd:sequence> <xsd:element name="home_phone" type="xsd:string"/> <xsd:element name="work_phone" type="xsd:string"/> <xsd:element name="cell_phone" type="xsd:string"/> <xsd:element name="fax_number" type="xsd:string"/> <xsd:element name="email_address" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema>

  7. Restriction bases - Restriction bases build on simple types but restrict the data structure, typically to a pattern. We have built a simple document called zipcode.xml that restricts the input to 5 or 9 digits (94020 or 94020-0007).

    <?xml version="1.0"?>
    
    <!-- This is a short little zipcode document that relates to zipcode_schema.xml -->
    <zipcodeType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                       xsi:noNamespaceSchemaLocation="zipcode.xsd">
        <zipcode>94020-0007</zipcode>
    </zipcodeType>

    The associated schema for this document is written in a file called zipcode_schema.xml.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="zipcodeType">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="zipcode" type="zipcodeType"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
        
        <xsd:simpleType name="zipcodeType">
            <xsd:restriction base="xsd:string">
                <xsd:pattern value="\d{5}(-\d{4})?"/>
            </xsd:restriction>
        </xsd:simpleType>
    </xsd:schema>

  8. Using number and date types - We can use number and date types as simple types that keep our data consistent with the needs of a validating application. For number types please see accounting.xml and accounting_schema.xml.

    <?xml version="1.0"?>
    <accounting xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      xsi:noNamespaceSchemaLocation="accounting_schema.xsd">
    	<accounts>
    		<savings>100.01</savings>
    		<checking>250.99</checking>
    		<money_market>500.59</money_market>
    	</accounts>
    </accounting>

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="accounting" type="accountingType"/>
        <xsd:element name="accounts" type="accountsType"/>
        <xsd:element name="checking" type="accountFormat"/>
        <xsd:element name="money_market" type="accountFormat"/>
        <xsd:element name="savings" type="accountFormat"/>

    <!-- ====================================================================== --> <!-- Globally defined types --> <!-- ====================================================================== --> <xsd:complexType name="accountingType"> <xsd:sequence> <xsd:element ref="accounts" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="accountsType"> <xsd:sequence> <xsd:element ref="savings"/> <xsd:element ref="checking"/> <xsd:element ref="money_market"/> </xsd:sequence> </xsd:complexType> <xsd:simpleType name="accountFormat"> <xsd:restriction base="xsd:decimal"> <xsd:totalDigits value="10"/> <xsd:fractionDigits value="2"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>

    For date types we can specify time, date, month, year, and century. These generally follow the CCYY-MM-DD and hh:mm:ss:sss formats. This is more detail then you'll probably ever need, so please see personal.xml and personal_schema.xml for examples that might fit your address book.

    <?xml version="1.0"?>
    
    <!-- this document will show personal data related to dates -->
    <!-- this document relates to the personal_schema.xml document -->
    <personal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:noNamespaceSchemaLocation="personal.xsd">
        <birthdate>1956-03-20</birthdate>
        <year_born>1956</year_born>
        <month_born>1956-03</month_born>
        <instant_born>1956-03-20T15:27:46.2398Z</instant_born>
        <birthday>--03-20</birthday>
    </personal>

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--W3C Schema generated by XML Spy v4.4 U (http://www.xmlspy.com)-->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
        <xsd:element name="personal">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element ref="birthdate"/>
                    <xsd:element ref="year_born"/>
                    <xsd:element ref="month_born"/>
                    <xsd:element ref="instant_born"/>
                    <xsd:element ref="birthday"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    
        <xsd:element name="birthdate" type="xsd:date"/>
        <xsd:element name="birthday" type="xsd:string"/>
        <xsd:element name="instant_born" type="xsd:dateTime"/>
        <xsd:element name="month_born" type="xsd:string"/>
        <xsd:element name="year_born" type="xsd:short"/>
    </xsd:schema>
    

  9. Enumeration values - Enumeration values specify or limit the entry of data to match only predefined choices. A typical example might be specifying months in a year, or astrological signs. An example of an enumeration value and the associated schema can be found in astrological.xml and astrological_schema.xml, respectively.

    <?xml version="1.0"?>
    <!-- this document will be used to show enumeration values -->
    <!-- the schema for this document can be seen in astrological_schema.xml -->
    <astrologicalType>
        <astrological>Pisces</astrological>
    </astrologicalType>

    <?xml version="1.0"?>
    
    <!-- This is the astrology schema that relates to astrological.xml -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="astrologicalType">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="astrological" type="astrologicalType"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    
        <xsd:simpleType name="astrologicalType">
            <xsd:restriction base="xsd:string">
                <xsd:enumeration value="Aries"/>
                <xsd:enumeration value="Taurus"/>
                <xsd:enumeration value="Gemini"/>
                <xsd:enumeration value="Cancer"/>
                <xsd:enumeration value="Leo"/>
                <xsd:enumeration value="Virgo"/>
                <xsd:enumeration value="Libra"/>
                <xsd:enumeration value="Scorpio"/>
                <xsd:enumeration value="Sagittarius"/>
                <xsd:enumeration value="Capricorn"/>
                <xsd:enumeration value="Aquarius"/>
                <xsd:enumeration value="Pisces"/>
            </xsd:restriction>
       </xsd:simpleType>
    </xsd:schema>

  10. Specifying patterns - for patterns please refer to the zipcode.xml and zipcode_schema.xml documents. See the section on restriction bases.

Section 4: Complex Types (Overview pg. 93)

  1. Only elements - An example of defining an element to contain only elements is shown in onlyElements.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to define the element record, which is the only element 
         contained inside the address_book root element whose complexType is called 
         "addressType" -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    	<xsd:complexType name="addressType">
    		<xsd:sequence>
    			<xsd:element name="record" type="recordType"/>
    		</xsd:sequence>
    	</xsd:complexType>
    </xsd:schema>

  2. Sequence - An example of declaring elements to appear in a given sequence is shown in sequence.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to force the element record, 
         whose complexType is called "recordType", to have three elements inside it, 
         name, address, and contact, and in that order. -->
    
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:complexType name="recordType">
            <xsd:sequence>
                <xsd:element name="name" type="nameType"/>
                <xsd:element name="address" type="addressType"/>
                <xsd:element name="contact" type="contactType"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:schema>

  3. Choice - An example of using choice if an element may appear or not is shown in choice.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to define the element nick_name as a choice inside the 
         "name" element where the complexType is named "nameType" -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
        <xsd:complexType name="nameType">
            <xsd:choice>
                <xsd:element name="nick_name" type ="nick_nameType" />
            </xsd:choice>
        </xsd:complexType>
    </xsd:schema>

  4. Any order - Elements can be declared to appear in any order, as shown in anyOrder.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to allow the element name, whose complexType is 
         called "nameType", to have the elements last_name, first_name, middle_name, 
         and nick_name, in any order. -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
      <xsd:complexType name="nameType">
        <xsd:all>
          <xsd:element name="last_name" type="lastNameType" minOccurs="1" maxOccurs="1" />
          <xsd:element name="first_name" type="firstNameType" minOccurs="1" maxOccurs="1" />
          <xsd:element name="middle_name" type="middleNameType" minOccurs="0" maxOccurs="1" />
          <xsd:element name="nick_name" type="nickNameType" minOccurs="0" maxOccurs="1" />
        </xsd:all>
      </xsd:complexType>
    </xsd:schema>

  5. Groups - You can define and name groups of elements as shown in groups.xml.

    <?xml version="1.0"?>
    <groups>
        <groupA>
            <first_name>Robert</first_name>
            <last_name>Cormia</last_name>
            <middle_name>Douglas</middle_name>
            <nick_name>Bob</nick_name>
            <street>200 Woodland Vista</street>
            <street_detail>PO Box 7</street_detail>
            <city>La Honda</city>
            <state>CA</state>
            <zipcode>94020-0007</zipcode>
        </groupA>
    
        <groupB>
            <street>Woodland Vista</street>
            <street_detail>PO Box 7</street_detail>
            <city>La Honda</city>
            <state>CA</state>
            <zipcode>94020-0007</zipcode>
            <home_phone>800-555-1212</home_phone>
            <work_phone>800-555-1212</work_phone>
            <cell_phone>800-555-1212</cell_phone>
            <email>rdcormia@earthlink.net</email>
            <website>http://www.rdcormia.com</website>
        </groupB>
    </groups>

  6. Referencing defined elements - After naming the groups, they can be referenced as shown in referenced.xml. This file uses groups declared as name, address, and contact and referenced to the element record. Record is a complex type that uses the sequence of named groups referenced above.

    <?xml version="1.0"?>
    
    <!-- This code will be used to define the element record, which is the only element 
         contained inside the address_book root element -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="record">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:group ref="name_elements"/>
                    <xsd:group ref="address_elements"/>
                    <xsd:group ref="contact_elements"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    
        <xsd:group name="name_elements">
            <xsd:sequence>
                <xsd:element name="first_name" type="xsd:string"/>
                <xsd:element name="last_name" type="xsd:string"/>
                <xsd:element name="middle_name" type="xsd:string"/>
                <xsd:element name="nick_name" type="xsd:string"/>
            </xsd:sequence>
        </xsd:group>
    
        <xsd:group name="address_elements">
            <xsd:sequence>
                <xsd:element name="street" type="xsd:string"/>
                <xsd:element name="street_detail" type="xsd:string"/>
                <xsd:element name="city" type="xsd:string"/>
                <xsd:element name="state" type="xsd:string"/>
                <xsd:element name="zipcode" type="xsd:string"/>
            </xsd:sequence>
        </xsd:group>
    
        <xsd:group name="contact_elements">
            <xsd:sequence>
                <xsd:element name="home_phone" type="xsd:string"/>
                <xsd:element name="work_phone" type="xsd:string"/>
                <xsd:element name="cell_phone" type="xsd:string"/>
                <xsd:element name="email" type="xsd:string"/>
                <xsd:element name="website" type="xsd:string"/>
            </xsd:sequence>
        </xsd:group>
    </xsd:schema>

  7. How many - You can control how many times an element appears using minOccurs and maxOccurs. These are shown in the example howMany.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to define the element record, which is the only 
         element contained inside the address_book root element -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="sibling" type="siblingType" />
    
        <xsd:complexType name="siblingType">
            <xsd:sequence>
                <xsd:element name="siblings" type="xsd:string" minOccurs="0" maxOccurs="1"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:schema>

  8. Define elements only text - Defining elements to contain only text is shown in onlyText.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to derive a text only complex type for an attribute called "year" 
         in a element called "age"-->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="age" type="ageType" />
    
        <xsd:complexType name="ageType">
            <xsd:simpleContent>
                <xsd:extension base="xsd:integer">
                    <xsd:attribute name="year" type="xsd:date"/>
                </xsd:extension>
            </xsd:simpleContent>
        </xsd:complexType>
    </xsd:schema>

  9. Define empty elements - page 103 content to go here. emptyElements.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to define the attributes of dimension for the element picture, 
         which will use a URL for the filemane and integers for dimensions of x and y-->
    <xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
        <xsd:element name="picture" type="pictureType" />
        
        <xsd:complexType name="pictureType">
            <xsd:extension base="anyType">
                <xsd:attribute name="filename" type="xsd:uri-reference"/>
                <xsd:attribute name="x" type="xsd:integer" />
                <xsd:attribute name="y" type="xsd:integer" />
            </xsd:extension>
        </xsd:complexType>
    </xsd:schema>

  10. Mixed content - Thanks to the mixed content attribute, we can create such things as paragraphs with text and links and elements indicating hidden attributes, such as meaning, as in mixedContent.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to define the element descritpion, which will contain mixed 
         content of two elements, one for a name and the other for a URL reference. -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="description" type="paragraph"/>
    
        <xsd:complexType name="paragraph" mixed="true">
            <xsd:sequence>
                <xsd:element name="name" type="xsd:string"/>
                <xsd:element name="link" type="xsd:anyURI"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:schema>

  11. Basing complex types on complex types - An example of complex types built on complex types is shown the example complexComplex.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to create complex types on complex types. Here we will 
         create declarations for birthType which is defined in birth_chracteristics -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:complexType name="characteristicsType">
            <xsd:sequence>
                <xsd:element name="height" type="xsd:string"/>
                <xsd:element name="weight" type="xsd:string"/>
                <xsd:element name="gender" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
    
        <xsd:element name="birth_characteristics" type="birthType"/>
    
        <xsd:complexType name="birthType">
            <xsd:complexContent>
                <xsd:extension base="characteristicsType">
                    <xsd:sequence>
                        <xsd:element name="mother" type="xsd:string"/>
                        <xsd:element name="birthdate" type="xsd:date"/>
                    </xsd:sequence>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:schema>

  12. Declare an element of complex type - An example of declaring an attribute of complex type is shown in declareComplex.xml.

    <?xml version="1.0"?>
    
    <!-- This code will be used to declare an element of complex type called 
         "characteristics" which will contain the elements height, weight, and gender. -->
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="characteristics" type="characteristicsType"/>
    	
        <xsd:complexType name="characteristicsType">
            <xsd:sequence>
                <xsd:element name="height" type="xsd:string"/>
                <xsd:element name="weight" type="xsd:string"/>
                <xsd:element name="gender" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:schema>

Section 5: Attributes

  1. Declaring attributes - While an attribute is always of simple type, since it contains neither elements nor attributes), it always appears within an element of complex type. Use <xsd:attribute to start the element, then give the attribute a "name" and a "type". Type will usually (or always) be one of the built in simple types. You can also reference an attribute group, as shown below. See address_schema_11.xml and picture_schema_1.xml for reference files.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
        <!-- The element "picture" will have attributes for "filename", "x" pixels 
             and "y" pixels -->
        <xsd:element name="picture">
            <xsd:complexType>
                <xsd:simpleContent>
                    <xsd:extension base="xsd:anyType">
                        <xsd:attribute name="filename" type="xsd:anyURI" use="required"/>
                        <xsd:attribute name="x" type="xsd:integer"/>
                        <xsd:attribute name="y" type="xsd:integer"/>
                    </xsd:extension>
                </xsd:simpleContent>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>

  2. Requiring an attribute - You can require an attribute by simply adding use="required" within <xsd:attribute . The default is "optional" so you do not have to specify it. See address_schema_12.xml and picture_schema_2.xml.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
        <!-- The element "picture" will have attributes for "filename", "x" pixels 
             and "y" pixels -->
        <xsd:element name="picture">
            <xsd:complexType>
                <xsd:simpleContent>
                    <xsd:extension base="xsd:anyType">
                        <xsd:attribute name="filename" type="xsd:anyURI" use="required"/>
                        <xsd:attribute name="x" type="xsd:integer" use="optional"/>
                        <xsd:attribute name="y" type="xsd:integer" use="optional"/>
                    </xsd:extension>
                </xsd:simpleContent>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>

  3. Predefining an attributes content - You can predefine an attribute's content by using the "fixed" attribute within the <xsd"attribute element, where fixed="value" is the predefined value. You may use one or the other but not both at the same time. Look at the following two examples to see how they are used: citizen_schema_1.xml

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    <!-- The element "citizenship" will have attribute for "country" which is 
         predefined as "USA" -->
        <xsd:element name="citzenship">
            <xsd:complexType>
                <xsd:complexContent>
                    <xsd:extension base="xsd:anyType">
                        <!-- below the value for citizenship has been set as "fixed" 
                             to "USA -->
                        <xsd:attribute name="country" type="xsd:string" fixed="USA" />
                    </xsd:extension>
                </xsd:complexContent>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>

    and citizen_schema_2.xml .

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
        <!-- The element "citizenship" will have attribute for "country" which is 
             predefined as "USA" -->
        <xsd:element name="citzenship">
            <xsd:complexType>
                <xsd:complexContent>
                    <xsd:extension base="xsd:anyType">
                        <!-- below the value for citizenship has been set as "default" 
                             to "USA -->
                    <xsd:attribute name="country" type="xsd:string" default="USA" />
                    </xsd:extension>
                </xsd:complexContent>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>

  4. Defining attribute groups - Attribute groups can be defined and later referenced to save time. Use <xsd:attributeGroup name="attribute_nameGroup" and name="whatever_Atts to name the group, as shown in picture_group_schema.xml.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
        <!-- The attribute group "pictureAtts" will have attributes for "filename", 
             "x" pixels and "y" pixels -->
        <xsd:attributeGroup name="pictureAtts">
            <xsd:complexType name="imagefileType">
                <xsd:attribute name="filename" type="xsd:anyURI" use="required"/>
                <xsd:attribute name="x" type="xsd:integer"/>
                <xsd:attribute name="y" type="xsd:integer"/>
            </xsd:complexType>
        </xsd:attributeGroup>
    </xsd:schema>

  5. Referencing attribute groups - After defining an attribute group above, you can reference it by using <xsd:attributeGroup ref="label" /> where "label" is the named group (above). See picture_schema_3.xml for examples of referencing attribute groups.

    <?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
        <!-- The element "picture" will reference pictureAtts attributes for "filename", 
             "x" pixels and "y" pixels -->
        <xsd:element name="picture">
            <xsd:complexType>
                <xsd:simpleContent>
                    <xsd:extension base="xsd:anyType">
                        <xsd:attributeGroup ref="pictureAtts"/>
                    </xsd:extension>
                </xsd:simpleContent>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>

Section 6: Creating Schema for Nested, Empty and Mixed Models

  1. Nested elements - Creating schema for nested files uses the complex type, sequence, and attribute declarations. These files are shown in nested_elements.xml, nested_elements_xsd.xml, and nested_elements.xsd

    <?xml version="1.0" encoding="UTF-8"?>
    <nested_elements xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:noNamespaceSchemaLocation="nested_elements.xsd">
        <outer_element block="1">
            <inner_element>text goes here</inner_element>
            <inner_element>text goes here</inner_element>
            <inner_element>text goes here</inner_element>
        </outer_element>

    <outer_element block="2"> <inner_element>text goes here</inner_element> <inner_element>text goes here</inner_element> <inner_element>text goes here</inner_element> </outer_element> <outer_element block="3"> <inner_element>text goes here</inner_element> <inner_element>text goes here</inner_element> <inner_element>text goes here</inner_element> </outer_element> </nested_elements>

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" 
                attributeFormDefault="unqualified">
        <xsd:element name="nested_elements" type="nested_elementsType">
            <xsd:annotation>
                <xsd:documentation>
                    This schema is designed around nested elements
                </xsd:documentation>
            </xsd:annotation>
        </xsd:element>

    <xsd:complexType name="nested_elementsType"> <xsd:sequence> <xsd:element name="outer_element" type="outer_elementType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="outer_elementType"> <xsd:sequence> <xsd:element name="inner_element" type="xsd:string" maxOccurs="unbounded"/> </xsd:sequence> <xsd:attribute name="block" type="xsd:string"/> </xsd:complexType> </xsd:schema>

  2. Empty elements - Creating schema for the empty model is straightforward. Declare the outer elements as a block, using a complexType declaration, and declare attributes of that block if present. Then declare the inner block as a complexType, with each attribute declared. Look carefully at the three files empty_elements.xml, empty_elements_xsd.xml, and empty_elements.xsd.

    <?xml version="1.0" encoding="UTF-8"?>
    <empty_elements xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:noNamespaceSchemaLocation="empty_elements.xsd">
        <outer_element block="1">
            <inner_element name="name" type="type" text="text"/>
            <inner_element name="name" type="type" text="text"/>
            <inner_element name="name" type="type" text="text"/>
        </outer_element>
    
        <outer_element block="2">
            <inner_element name="name" type="type" text="text"/>
            <inner_element name="name" type="type" text="text"/>
            <inner_element name="name" type="type" text="text"/>
        </outer_element>
    
        <outer_element block="3">
            <inner_element name="name" type="type" text="text"/>
            <inner_element name="name" type="type" text="text"/>
            <inner_element name="name" type="type" text="text"/>
        </outer_element>
    </empty_elements>

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" 
                attributeFormDefault="unqualified">
        <xsd:element name="empty_elements" type="empty_elementsType">
            <xsd:annotation>
                <xsd:documentation>
                    This schema is designed around empty elements
                </xsd:documentation>
            </xsd:annotation>
        </xsd:element>
    
        <xsd:complexType name="empty_elementsType">
            <xsd:sequence>
                <xsd:element name="outer_element" type="outer_elementType" 
                             maxOccurs="unbounded"/>
            </xsd:sequence>
        </xsd:complexType>
    
        <xsd:complexType name="outer_elementType">
            <xsd:sequence>
                <xsd:element name="inner_element" type="inner_elementType" 
                             maxOccurs="unbounded"/>
            </xsd:sequence>
            <xsd:attribute name="block" type="xsd:string"/>
        </xsd:complexType>
    
        <xsd:complexType name="inner_elementType">
            <xsd:attribute name="name" type="xsd:string" use="optional"/>
            <xsd:attribute name="type" type="xsd:string" use="optional"/>
            <xsd:attribute name="text" type="xsd:string" use="optional"/>
        </xsd:complexType>
    </xsd:schema>

  3. Mixed elements - Creating schema for mixed models is only slightly more complicated than empty. Look carefully at the three files mixed_elements.xml, mixed_elements_xsd.xml, and mixed_elements.xsd. Notice that the only difference is that you are using simpleContent and an extension base to allow you to declare the 'mixed content' of attributes and text in the inner elements.

    <?xml version="1.0" encoding="UTF-8"?>
    <mixed_elements xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:noNamespaceSchemaLocation="mixed_elements.xsd">
      <outer_element block="1">
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
      </outer_element>
    
      <outer_element block="2">
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
      </outer_element>
    
      <outer_element block="3">
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
        <inner_element name="name" type="type" text="text">inner element text</inner_element>
      </outer_element>
    </mixed_elements>

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" 
                attributeFormDefault="unqualified">
        <xsd:element name="mixed_elements" type="mixed_elementsType">
            <xsd:annotation>
                <xsd:documentation>
                    This schema is designed around mixed elements that contain both 
                    elements and attributes and attributes and text
                </xsd:documentation>
            </xsd:annotation>
        </xsd:element>
    
        <xsd:complexType name="mixed_elementsType">
            <xsd:sequence>
                <xsd:element name="outer_element" type="outer_elementType" 
                             maxOccurs="unbounded"/>
            </xsd:sequence>
        </xsd:complexType>
       
        <xsd:complexType name="outer_elementType">
            <xsd:sequence>
                <xsd:element name="inner_element" type="inner_elementType" 
                             maxOccurs="unbounded"/>
            </xsd:sequence>
            <xsd:attribute name="block" type="xsd:string"/>
        </xsd:complexType>
    
        <xsd:complexType name="inner_elementType">
            <xsd:simpleContent>
                <xsd:extension base="xsd:string">
                    <xsd:attribute name="name" type="xsd:string" use="optional"/>
                    <xsd:attribute name="type" type="xsd:string" use="optional"/>
                    <xsd:attribute name="text" type="xsd:string" use="optional"/>
                </xsd:extension>
            </xsd:simpleContent>
        </xsd:complexType>
    </xsd:schema>

  4. Mixed content - These files contain text and elements mixed together - addressing the issue of 'unstructured text'. Take a look at these files, including their DTD counterparts: story.xml, story_dtd.xml, story_xsd.xml, story.dtd, and story.xsd, or the entire zipped archive story.zip.

    The following files are the schema files, story_xsd.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <story xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                 xsi:noNamespaceSchemaLocation="story.xsd">
        <chapter id="1">
            <para id="1">
                Some words will go here and a 
                <fact>will appear here</fact> and then my initials. 
                <name>RDC</name>Some more words will go here and a 
                <fact>will appear here</fact> and then my initials again 
                <name>RDC</name>.
            </para>
            <para id="2">
                Some words will go here and a 
                <fact>will appear here</fact> and then my initials. 
                <name>RDC</name>Some more words will go here and a 
                <fact>will appear here</fact> and then my initials again <name>RDC</name>.
            </para>
            <para id="3">
                Some words will go here and a <fact>will appear here</fact> 
                and then my initials. <name>RDC</name>Some more words will go here and a 
                <fact>will appear here</fact> and then my initials again <name>RDC</name>.
            </para>
            <para id="4">
                Some words will go here and a <fact>will appear here</fact> 
                and then my initials. <name>RDC</name>Some more words will go here and a 
                <fact>will appear here</fact> and then my initials again <name>RDC</name>.
            </para>
            <para id="5">
                Some words will go here and a <fact>will appear here</fact> 
                and then my initials. <name>RDC</name>Some more words will go here and a 
                <fact>will appear here</fact> and then my initials again <name>RDC</name>.
            </para>
            <para id="6">
                And only text is in this element. So all the other elements are optional
            </para>
        </chapter>
    </story>

    and story.xsd.

    <?xml version="1.0" encoding="UTF-8"?>
    <!--W3C Schema generated by XML Spy v4.4 U (http://www.xmlspy.com)-->
    
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
        <xsd:complexType name="chapterType">
            <xsd:sequence>
                <xsd:element name="para" type="paraType" maxOccurs="unbounded"/>
            </xsd:sequence>
            <xsd:attribute name="id" type="xsd:integer" use="required"/>
        </xsd:complexType>
    
        <xsd:element name="fact" type="xsd:string"/>
        <xsd:element name="name" type="xsd:string"/>
    
        <xsd:complexType name="paraType" mixed="true">
            <xsd:choice minOccurs="0" maxOccurs="unbounded">
                <xsd:element ref="fact"/>
                <xsd:element ref="name"/>
            </xsd:choice>
            <xsd:attribute name="id" type="xsd:integer" use="required"/>
        </xsd:complexType>
    
        <xsd:element name="story">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="chapter" type="chapterType"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>

Section 7: The Address Book Schema

Below are the nine files that represent the address book files in nested, empty, and mixed models. These are worth viewing and comparing.

  1. address_book_nested.xml
  2. address_book_nested.xsd
  3. address_book_nested_xsd.xml
  4. address_book_empty.xml
  5. address_book_empty.xsd
  6. address_book_empty_xsd.xml
  7. address_book_mixed.xml
  8. address_book_mixed.xsd
  9. address_book_mixed_xsd.xml
  10. address_schema.zip (all 9 above)

Tutorials and Resources

Powerpoint Presentations

Links to XML Related Sites

  1. XML.COM
  2. WDVL XML tutorial
  3. Sun Java XML Introduction
  4. IBM'S XML Website
  5. Google Directory on XML

Up Arrow Top