Complex Data Types

[Previous] [Next]

A data type can either be simple or complex. Simple data types include the data types discussed in the previous section. Complex data types contain the child elements that belong to an element, as well as all the attributes that are associated with the element. If you visit http://www.w3.org/TR/xmlschema-1/, you'll find the first schema specification. Combining this specification with that for simple data types, you will have the complete schema specification. Our discussion of complex data types in this section will include an explanation of all of the elements of a schema, a sample DTD for a schema, and numerous examples showing how to create a schema and complex data types.

Viewing Schemas in XML Tools

On the companion CD, you'll find a file named XHTMLschema.xsd, which is a schema document based on a schema generated by XML Authority. The schema was generated from the XHTML DTD we created in Chapter 5. You can open XHTMLschema.xsd in XML Authority version 1.2 or higher.

Because schemas are written as well-formed XML documents, you can also view the schema in any other XML tools, such as XML Spy or Microsoft XML Notepad. For example, Figure 7-1 shows the schema as it would appear in XML Spy.

click to view at full size.

Figure 7-1. The schema in XML Spy.

As you can see in Figure 7-1, a schema has a well-defined structure. This structure includes a root element named schema, with one or more element child elements. These element elements can have complexType child elements; the complexType elements can in turn have annotation, group, attributeGroup, and attribute child elements. Clearly, this schema is a well-formed XML document.

Important Elements in XHTMLschema.xsd

In Figure 7-1, you can also see that the essential components of a schema are element, complexType, and simpleType elements. Essentially, a schema is all about associating data types with element elements. A portion of the source code from XHTMLschema.xsd is shown below.

 <schema targetNamespace = "XHTMLschema.xsd"     xmlns = "http://www.w3.org/xmlschema">     <element name = "html">         <complexType content = "elementOnly">             <annotation> <documentation>  a Uniform Resource Identifier, see [RFC2396] </documentation>             </annotation>         <group>             <sequence>                 <element ref = "head"/>                 <element ref = "body"/>             </sequence>         </group>         <attributeGroup ref = "i18n"/>         </complexType>     </element>     <element name = "head">         <complexType content = "elementOnly">         <group>             <sequence>                 <element ref = "title"/>                 <element ref = "base" minOccurs = "0"                      maxOccurs = "1"/>             </sequence>         </group>         <attributeGroup ref = "i18n"/>         <attribute name = "profile" type = "string"/>         </complexType>     </element>     <element name = "title">         <complexType content = "textOnly">             <attributeGroup ref = "i18n"/>         </complexType>     </element>     <element name = "base">         <complexType content = "empty">             <attribute name = "target" use = "required"                 type = "string"/>         </complexType>     </element>     <element name = "atop">         <complexType content = "elementOnly">             <sequence>                 <element ref = "p"/>                 <element ref = "a"/>             </sequence>         </complexType>     </element>     <element name = "body">         <complexType content = "elementOnly">             <group>                 <sequence>                     <element ref = "basefont" minOccurs = "0"                          maxOccurs = "1"/>                     <element ref = "table"/>                 </sequence>             </group>            <attribute name = "alink" type = "string"/>            <attribute name = "text" type = "string"/>            <attribute name = "bgcolor" type = "string"/>            <attribute name = "link" type = "string"/>            <attribute name = "vlink" type = "string"/>         </complexType>     </element>          <element name = "h1">         <complexType content = "elementOnly">             <sequence>                 <group ref = "Inline" />             </sequence>             <attributeGroup ref = "attrs"/>             <attribute name = "align" type = "string"/>         </complexType>     </element>      </schema> 

NOTE
This listing shows only parts of the schema. For the full schema, refer to the version of the document on the companion CD.

This particular version of the schema does not use anything like the entities in a DTD—everything is listed out here. Schemas do provide components that are similar to parameter entities, which will be discussed later in this chapter. Comments located within the schema element are contained within documentation elements. The schema element is the root for the document. The schema element and other elements and attributes will be discussed in detail in the next section.

A DTD for Schemas

The schema specification provides a fairly complex DTD that can be used to define every possible schema. This DTD is designed to work with a wide range of possible schemas and to cover every possible condition. Here we'll work with a simplified DTD that presents a subset of the schema specification DTD. Any schema that conforms to the simplified DTD will also conform to the schema specification DTD.

A simplified DTD for schemas is shown below. (For the full DTD, visit http://www.w3.org/TR/xmlschema-1 to see the schema specification.)

 <!ENTITY % xs-datatypes PUBLIC 'datatypes' 'Datatypes.dtd'> %xs-datatypes; <!ELEMENT schema ((include | import | annotation )*, (element, simpleType, complexType, attributeGroup, group, notation)*> <!ATTLIST schema targetNamespace CDATA #IMPLIED version CDATA #IMPLIED xmlns CDATA #REQUIRED xmlns:dt CDATA #REQUIRED > <!ELEMENT element ((annotation)?, (complexType | simpleType)?, (unique | key | keyref)*)> <!ATTLIST element type CDATA #IMPLIED name CDATA #IMPLIED ref CDATA #IMPLIED minOccurs (1 | 0 ) #IMPLIED maxOccurs CDATA #IMPLIED id ID #IMPLIED nullable (true | false ) 'false' default CDATA #IMPLIED fixed CDATA #IMPLIED > <!ELEMENT complexType (((annotation)? , (%ordered;, %unordered;)* | (element | all | choice | sequence | group | any )*, (attribute | attributeGroup) , anyAttribute )> <!ATTLIST complexType content (mixed | empty | textOnly | elementOnly ) #REQUIRED name CDATA #REQUIRED derivedBy "(restriction|extension|reproduction)" #IMPLIED base CDATA #IMPLIED id ID #IMPLIED final block> <!ELEMENT group ((annotation)?, (all | choice | sequence)*)> <!ATTLIST group minOccurs CDATA '1' maxOccurs CDATA #IMPLIED order (choice | seq | all) 'seq' name CDATA #IMPLIED ref CDATA #IMPLIED id ID #IMPLIED> <!ELEMENT all ((annotation)?, (element | group | any | choice | sequence)*)> <!ATTLIST all minOccurs CDATA #FIXED '1' maxOccurs CDATA #FIXED '1' id ID #IMPLIED> <!ELEMENT choice ((annotation)?, (element | group | any | choice | sequence)*)> <!ATTLIST choice minOccurs CDATA '1' maxOccurs CDATA #IMPLIED id ID #IMPLIED> <!ELEMENT sequence ((annotation)?, (element | group | any | choice | sequence)*)> <!ATTLIST sequence minOccurs CDATA '1' maxOccurs CDATA #IMPLIED id ID #IMPLIED> <!ELEMENT attribute ((annotation)?, (simpleType)? )> <!ATTLIST attribute type CDATA #IMPLIED default CDATA #IMPLIED fixed CDATA #IMPLIED name CDATA #REQUIRED minOccurs (0|1) '0' maxOccurs (0|1) '1' > <!ELEMENT attributeGroup ((annotation)?, (attribute | attributeGroup)*, (anyAttribute)?)> <!ELEMENT anyAttribute EMPTY> <!ATTLIST anyAttribute namespace CDATA '##any'> <!ELEMENT unique ((annotation)?, selector, (field)+)> <!ATTLIST unique name CDATA #REQUIRED id ID #IMPLIED uniqueAttrs> <!ELEMENT key ((annotation)?, selector, (field)+)> <!ATTLIST key name CDATA #REQUIRED id ID #IMPLIED keyAttrs> <!ELEMENT keyref ((annotation)?, selector, (field)+)> <!ATTLIST keyref name CDATA #REQUIRED id ID #IMPLIED refer CDATA #REQUIRED> <!ELEMENT any EMPTY> <!ATTLIST any namespace CDATA '##any' processContents (skip|lax|strict) 'strict' minOccurs CDATA '1' maxOccurs CDATA #IMPLIED> <!ELEMENT selector (#PCDATA)> <!ELEMENT field (#PCDATA)> <!ELEMENT include EMPTY> <!ATTLIST include schemaLocation CDATA #REQUIRED> <!ELEMENT import EMPTY> <!ATTLIST import namespace CDATA #REQUIRED schemaLocation CDATA #IMPLIED> 

This DTD includes all the essential elements of a schema and also includes the data types' DTD. All the schema elements that will be defined in this chapter are listed. Notice that the elements you saw in XML Spy are now much more visible. The DTD uses a set of elements and attributes to define the structure of a schema document. The principal elements of a schema are simpleType, datatype, enumeration, schema, annotation, complexType, element, attribute, attributeGroup, and group. We've already looked at the first three elements; we'll examine the remaining elements next.

The schema Element

The schema element corresponds to the root element defined in a DTD. In a schema, all element elements are child elements of the schema root element. We will discuss the attributes of the schema element in the section on namespaces in this chapter.

NOTE
Technically speaking, the DTD for a schema in the specification does not require that the schema element be the root element. The usual definition of a schema does have a schema element as the root, however.

The annotation Element

The annotation element is used to create comments within the complexType element. Comments are contained within one of two possible child elements of the annotation element: appinfo and documentation. The documentation element is used for human-readable comments. The appinfo elements are used for application-readable comments, as shown here:

 <annotation> <appinfo> The machine-readable comment goes here. </appinfo> </annotation> 

Notice that the comment is content of the annotation element, which means that it is not enclosed in the usual comment symbols (<!--… -->). When the annotation element is an allowable child element for an element, it will always be the first child element.

The complexType Element

You can think of the complexType element as equivalent to a combination of the attributes and the child element list enclosed in parentheses in the element element declaration used in a DTD—essentially, it defines the child elements and attributes for an element element. The complexType element will define the element elements, attributes, or a combination that will be associated with an element element that has attributes or child elements. The simplified DTD in "A DTD for Schemas" declared the complexType element as follows:

 <!ELEMENT complexType ( ((annotation)?, (%ordered;, %unordered;)*| (element | all | choice | sequence | group | any )*, (attribute | attributeGroup), anyAttribute)> <!ATTLIST complexType content (mixed | empty | textOnly | elementOnly) #REQUIRED name CDATA #REQUIRED derivedBy "(restriction|extension|reproduction)"> #IMPLIED base CDATA #IMPLIED id ID #IMPLIED > 

The complexType element can contain three types of elements in the following order: comment, element, and attribute. The comment is located in the annotation element. Element information is usually defined using element or group elements. You can also use choice, sequence, any, or all elements to define the attributes within a complexType, as described later in this section. Attributes can be defined using the attribute, attributeGroup, or group elements.

The schema in "A DTD for Schemas" uses what is called an embedded complexType declaration—the declaration is embedded in the element declaration. The following fragment shows the complexType element embedded within the element element:

 <element name = "title"> <complexType content = "textOnly"> <attributeGroup ref = "i18n"/> </complexType> </element> 

The complexType declarations have a scope, specifying where the data type can be seen in the document. Embedded datatype declarations can be seen only within the element in which they are embedded—that is, they have local scope. Thus, the title element can see the complexType element declared inside of it, but this complexType declaration is not visible from anywhere else in the document. You can also declare complexType elements outside of an element element. The complexType elements declared outside the element element are visible to the entire document and have document scope. You can reference a document scope element using the ref attribute. The document scope complexType elements will be discussed in detail later in this chapter.

NOTE
As we have mentioned, the schema element can contain element, simpleType, complexType, atttributeGroup, and group elements as child elements. When any of these elements are child elements of the schema element, they also have document scope.

The content attribute can be textOnly, mixed, elementOnly, or empty. If the content consists of only text and no elements, you can use textOnly. For both text and elements, you would use mixed. If the content is only elements, you would use elementOnly. When there is no content, you can use empty.

The ref attribute is used to reference document scope elements. The ref attribute can be used with attributeGroup, element, and group elements. When used with the attributeGroup element, it can reference only simpleType elements.

When an element element is included as the content of the complexType element, it represents a child element. Thus, the following code declares a child element of h1:

 <element name = "h1"> <complexType content = "mixed"> <element ref = "a"/>  

Notice that the ref attribute is used to reference the name of the child element, in this case, a.

You can also use the minOccurs and maxOccurs attributes with the child element to specify its occurrence, as shown here:

 <element name = "h1"> <complexType content = "mixed"> <element ref = "a" minOccurs = "0" maxOccurs = "1"/>  

We'll discuss the minOccurs and maxOccurs attributes in the next section. When you use an element that uses the ref attribute, it's as if the element that is being referenced is substituting the element that contains the ref attribute.

The element Element

As shown in the code in "A DTD for Schemas," the simplified DTD declaration for an element element is as follows:

 <!ELEMENT element ((annotation)?, (complexType | simpleType)?, (unique | key | keyref)*)> <!ATTLIST element type CDATA #IMPLIED name CDATA #IMPLIED ref CDATA #IMPLIED minOccurs (1 | 0 ) #IMPLIED maxOccurs CDATA #IMPLIED id ID #IMPLIED nullable (true | false ) 'false' default CDATA #IMPLIED fixed CDATA #IMPLIED > 

The name attribute is the name of the element. The name attribute must follow all the rules defined for DTD element names. You can define your element using a complexType element, a simpleType element, or a type attribute. The type attribute and either the simpleType element or the complexType element are mutually exclusive. If you are declaring a data type, then one and only one of these must be used for the datatype declaration to be valid.

The type attribute

The type attribute associates either a simple or complex data type with an element. As we've seen, simple data types are either the predefined simple data types or simple data types you define based on these predefined simple data types. Complex data types can be used to associate attributes, elements, or a combination of both to an element. For example, you can declare the simple data type String24 and associate it with the customerName element, as shown here:

 <simpleType name="String24" base="string"> <maxLength= "24"/ > <minLength = "0"/> </simpleType> <element name = "customerName" type = "String24"/> 

In this case, you have created a data type named String24 that has a length between 0 and 24 characters. This data type is then used in the element declaration, which means that the customerName element will be a string that is between 0 and 24 characters.

The customerName declaration uses document scope, meaning that all elements in the document can see the String24 data type. The type attribute can be used to assign either a complex or a simple data type with document scope to an element.

The minOccurs and maxOccurs attributes

Notice that the minOccurs and maxOccurs attributes are also used in the DTD declaration for an element element to specify the number of occurrences of an element. When working with DTDs, we used the markers *, ?, and + to indicate the number of times a particular child element could be used as content for an element. For attributes, we used #IMPLIED for optional attributes, #REQUIRED for required attributes, #FIXED for attributes that had a fixed default value, and a default value when the attribute was optional. In schemas, both elements and attributes use the minOccurs and maxOccurs attributes. The minOccurs and the maxOccurs attributes are also used with the group element; the choice, sequence, and all elements that are contained within the group element; and the any element.

When used with elements, the minOccurs and maxOccurs attributes specify the number of occurrences of the element. For example, if an element has a minOccurs value of 0, the element is optional. You can also declare an element to occur one or more times by setting a maxOccurs attribute to 1 or * respectively. The default value for minOccurs is 1, and maxOccurs has no default value.

When used with attributes, minOccurs and maxOccurs indicate whether the attribute is required. The maxOccurs attribute defaults to 1 unless it is specified or minOccurs is greater than 1. If minOccurs is set to 0 for an attribute and the default maxOccurs is equal to 1, you can have between 0 and 1 occurrences of this attribute. Thus, an attribute with minOccurs set to 0 is optional. If minOccurs is set to 1, the attribute is required. The default for minOccurs is 0, but it's better to specify a value for it in your schema. The minOccurs and maxOccurs attributes can be set only to 0 or 1. For example, the following declaration makes the target attribute required:

 <attribute name = "target" minOccurs = "1" maxOccurs = "1" type = "string"/> 

Notice that the attributes we have discussed in this section can also be used to define other elements such as the attribute element.

The attribute Element

Attributes were declared in the simplified DTD in "A DTD for Schemas" as follows:

 <!ELEMENT attribute ((annotation)?, (simpleType)?)> <!ATTLIST attribute type CDATA #IMPLIED default CDATA #IMPLIED fixed CDATA #IMPLIED name CDATA #REQUIRED minOccurs (0|1) '0' maxOccurs (0|1) '1' > 

In schemas, attributes are the association of a name with a particular simple data type. The attribute element is not included in the schema element, and therefore can only be used as a child element of the complexType or attributeGroup element. This means that all attribute elements will have local scope.

You can use the attribute element within a complexType element that has either local or document scope. As we'll see in the next section, you can group attribute elements together in an attributeGroup element. The name attribute must follow the same naming conventions as attribute names for DTDs.

You can use either a default attribute or a fixed attribute with attribute elements, but not both for the same attribute element. Unlike in DTDs, the fixed and default values are not linked to an attribute as optional or required—you can choose to make any attribute have a fixed value or a default value. A fixed value cannot be changed. The value of the default attribute will be the default value if one is not supplied for the attribute. The following declarations show the usage of default and fixed attributes:

 <attribute name = "myAttribute" minOccurs = "1" fixed = "preserve" type = string"/> <attribute name = "align" minOccurs = "0" default = "Center" type = "string"/> 

The attributeGroup Element

As you can see in the simplified DTD for schemas in "A DTD for Schemas," there is nothing equivalent to the DTD parameter entity used for attributes in schemas. Schemas do, however, allow you to create something similar to a parameter entity for attributes by using the attributeGroup element. Attribute groups declared using the attributeGroup element can have either document-level scope or local scope. (The element can be included in the declaration of the schema element or in the declaration of the complexType element.) In the original version of the schema, all attributes were defined without using the attributeGroup element.

The sample DTD we created in Chapter 5 included a parameter entity named attrs. You can define an attribute group named attrs in your schema as follows:

 <schema> <attributeGroup name="attrs"> <attribute name = "id" type = "ID"/> <attribute name = "class" type = "string"/> <attribute name = "style" type = "string"/> <attribute name = "lang" type = "NMTOKEN"/> <attribute name = "xml:lang" type = "NMTOKEN"/> <attribute name = "dir"> <simpleType source = "ENUMERATION"> <enumeration value = "ltr"/> <enumeration value = "rtl"/> </simpleType> </attribute> <attribute name = "onclick" type = "string"/> <attribute name = "ondblclick" type = "string"/> <attribute name = "onmousedown" type = "string"/> <attribute name = "onmouseup" type = "string"/> <attribute name = "onmouseover" type = "string"/> <attribute name = "onmousemove" type = "string"/> <attribute name = "onmouseout" type = "string"/> <attribute name = "onkeypress" type = "string"/> <attribute name = "onkeydown" type = "string"/> <attribute name = "onkeyup" type = "string"/> <attribute name = "href" type = "string"/> <attribute name = "name" type = "string"/> <attribute name = "target" type = "string"/> </attributeGroup>  </schema> 

You can use attrs as follows:

 <element name = "option"> <type content = "textOnly"> <attributeGroup ref = "attrs"/> <attribute name = "selected"/>  

Thus, you declare the attributeGroup element as a child element of the schema element to create a document scope group of attributes. You can then reference the document scope attributeGroup element in a type element by including an attributeGroup element in the type element with the ref attribute set equal to the name of the document scope group. As you can see, this greatly simplifies the schema.

NOTE
Attribute groups can contain only simple data types.

The group Element

The group element enables you to group elements in the same way you use parentheses when declaring elements in a DTD. The group element also enables you to create something similar to DTD parameter entities. The order of the elements in the group element can vary as defined by the order attribute.

The declaration for a group element looks like this:

 <!ELEMENT group ((annotation)?, (all | choice | sequence)*)> <!ATTLIST group minOccurs CDATA '1' maxOccurs CDATA #IMPLIED order (choice | seq | all) 'seq' name CDATA #IMPLIED ref CDATA #IMPLIED id ID #IMPLIED> 

A group element can optionally contain an annotation element (comments) and must contain an all, a choice, or a sequence element. These elements define the order and usage of the elements in the group, and are examined in detail in the next section. Notice that group elements do not include attributes—they are used only for grouping elements.

The minOccurs and maxOccurs attributes indicate how many times the group element can occur. They replace the markers (*, ?, and +) in the DTD.

The choice, sequence, and all elements

The choice element indicates a choice of elements in the group element—its function is the same as the bar (|) in the DTD. The DTD declaration <!ELEMENT select (optGroup | option )+> would thus become the following schema declaration:

 <group minOccurs = "1" maxOccurs = "*"> <choice> <element ref = "optGroup"/> <element ref = "option"/> </choice> </group> 

The sequence element indicates that the elements must appear in the sequence listed and that each element can occur 0 or more times. When using sequence, you can use minOccurs and maxOccurs as attributes for the elements to specify the number of allowable occurrences of an element element in the group. Using sequence is the same as using the comma separator in the DTD with subgroups that are enclosed in parentheses with occurrence operators. In its simplest form, a sequence element can consist of only one element. For example, the DTD declaration <!ELEMENT optGroup (option )+> would look like this in a schema declaration:

 <group minOccurs = "1" maxOccurs = "*"> <sequence> <element ref = "option"/> </sequence> </group> 

The DTD declaration <!ELEMENT ol (font? , li+ )> would look like this as a schema declaration:

 <group > <sequence> <element ref = "font" minOccurs = "0" maxOccurs = "1"/> <element ref = "li" minOccurs = "1" maxOccurs = "*"/> </sequence> </group> 

The all element indicates that all the element and group elements listed in the schema must be used, in any order. Each element element in an all group element must have minOccurs and maxOccurs attributes set to 1. The minOccurs and maxOccurs attributes cannot be used for the group element when you are using all; they can be used only for the element elements in the group. A group element declared with order equal to all must not be a subgroup of another group element. For example, because every HTML document must have one and only one head and body, you could declare them in your schema as follows:

 <group > <all> <element ref = "head" minOccurs= "1" maxOccurs= "1"/> <element ref = "body" minOccurs= "1" maxOccurs= "1"/> </all> </group> 

Local embedded groups

When you include the group element declaration within a complexType element, you are embedding the group element declaration inside the complexType element. If you define the group element within the complexType element, that group element is not visible from anywhere else within the schema document—it has local scope. If you are going to use a group element to contain only one element, it makes sense to use a local group.

Wildcards, particles, and compositors

According to the schema specification, the term particle refers to content of an element element that contains only other elements, groups, and wildcards—in other words, no text. Wildcards include several different ways to use the any keyword.

NOTE
The any keyword in schemas is similar to the ANY keyword in DTDs, except that in a schema any refers only to element and group elements. In a DTD, ANY refers to text and elements. Text content is not part of the any keyword in the schema specification.

One way to reference all element or group elements within the specified namespace and schema as the complexType element is to use the any keyword. If this keyword is used within a complexType element, it indicates that any element or group in the schema in the same namespace as the complexType element could be included within this complextype element. If the value for the namespace is ##targetNamespace, all of the elements within the current document will be used.

Another possibility is to reference all element and group elements in a namespace other than the one the complexType element is in. In this case, you would use the following declaration:

 <any namespace="##name_of_namespace"/> 

In a schema, the order element and the minOccurs and maxOccurs attributes together define what is called a compositor. A compositor for a given group element will specify whether elements in the group provide the following conditions:

  • A sequence of the elements that are permitted or required by the specified particles
  • A choice between the elements permitted or required by the specified particles
  • A repeated choice among the elements permitted or required by the specified particles
  • A set of the elements required by the specified particles

A more precise definition can now be created: a group consists of two or more particles plus a compositor.

Document scope groups

Just as you can create complexType elements that have document scope, you can create group elements that have document scope. The same basic rules apply—that is, including a name attribute and declaring the elements as child elements of the schema element. Thus, you could create the following global group elements:

 <schema> <group name = "Block" minOccurs = "1" maxOccurs = "*"> <choice> <element ref = "p"/> <element ref = "h1"/> <element ref = "h2"/> <element ref = "h3"/> <element ref = "h4"/> <element ref = "h5"/> <element ref = "h6"/> <element ref = "div"/> <group > <choice> <element ref = "ul"/> <element ref = "ol"/> </choice> </group> <element ref = "hr"/> <element ref = "blockquote"/> <element ref = "fieldset"/> <element ref = "table"/> <element ref = "form"/> <element ref = "script"/> <element ref = "noscript"/> </choice> </group>  </schema> 

This declaration states that any element that uses this group must include at least one of these elements as its content. The content of the element can also be any number of copies of the elements in any order. This declaration is identical to the DTD declaration shown here:

 <!ENTITY % Block " (%block; | form | %misc;)*"> <!ELEMENT noscript %Block;> 

Thus, document scope group elements allow you to create something similar to the parameter entities in DTDs that contained element declarations. You can now use the group element as follows:

 <element name = "noscript"> <complexType content = "elementOnly"> <group ref = "Block"/> <attributeGroup ref = "attrs"/> </complexType> </element> <element name = "blockquote"> <complexType content = "elementOnly"> <group ref = "schemaBlock"/> <attributeGroup ref = "attrs"/> <attribute name = "cite" type = "string"/> </complexType> </element> 

complexType Elements with Document Scope

Now that we've covered group and attributeGroup elements, we can examine document scope complexType elements in more detail. If you have a grouping of attributes and elements that will be used by more than one element element, you can create a document scope complexType element. You declare the document scope complexType element exactly as you declare the embedded complexType element, except the declaration will include the name attribute and will not be within the content of an element element—that is, it will be outside an element element declaration. Thus, it will be declared as a child element of the schema element. For example, all the h elements share a common set of child elements and attributes. You could declare a global complexType element and use it as shown here:

 <schema> <complexType name= "standardcontent" content = "mixed"> <element ref = "a"/> <element ref = "br"/> <element ref = "span"/> <element ref = "img"/> <element ref = "tt"/> <element ref = "i"/> <element ref = "b"/> <element ref = "big"/> <element ref = "small"/> <element ref = "em"/> <element ref = "strong"/> <element ref = "q"/> <element ref = "sub"/> <element ref = "sup"/> <element ref = "input"/> <element ref = "select"/> <element ref = "textarea"/> <element ref = "label"/> <element ref = "button"/> <element ref = "script"/> <element ref = "noscript"/> <attribute name = "align" type = "string"/> <attributeGroup ref = "attrs"/> </complexType> <element name= "h1" type ="standardcontent"/> <element name= "h2" type ="standardcontent"/>  </schema> 

You can also extend a complexType element using the base attribute. For example, the li element uses all the preceding content and several other elements. You can extend the complexType element example as follows:

 <complexType name = "licontent" base = "standardcontent" derivedby = "extension"> <element ref = "p"/> <element ref = "h1"/> <element ref = "h2"/> <element ref = "h3"/> <element ref = "h4"/> <element ref = "h5"/> <element ref = "h6"/> <element ref = "div"/> <element ref = "ul"/> <element ref = "ol"/> <element ref = "hr"/> <element ref = "blockquote"/> <element ref = "fieldset"/> <element ref = "table"/> <element ref = "form"/> </complexType> <element name= "li" type ="licontent"/>  

To extend a complexType element, you need to use the base and derivedBy attributes of the complexType element. The base attribute identifies the source of the element and can be either #all, a single element, or a space-separated list. The derivedBy attribute can be set to restriction, extension, or reproduction. When you are adding elements or attributes to a complexType element, the derivedBy attribute should be set to extension.

The restriction value for the derivedBy attribute allows you to add restrictions to the element elements included within the complexType element. For element elements included in the original complexType element, you can restrict the number of occurrences of an element or replace a wildcard with one or more elements. For example, if you wanted to restrict the a element to one or more occurrences and remove the br element in a new complexType element, based on the standardcontent type defined in the preceding example, you could write the following code:

 <type name = "licontent" base = "standardcontent" derivedby = "restriction"> <element name = "a" minOccurs = "1"/> <element name ="br" maxOccurs ="0"/> </type> 

For attributes, you can add or fix defaults or restrict the attribute's simple data type definition.

If you set the derivedBy attribute to reproduction, the new element is identical to the type it is derived from. Essentially, reproduction indicates neither restriction nor extension.

If the value for the final attribute for the complexType element is not empty, the complexType cannot be extended, restricted, or reproduced. A complexType that is derived by extension, restriction, or reproduction also cannot be extended, restricted, or reproduced. The block attribute allows you to block extension, restriction, or reproduction. If you set the block attribute to restriction, the complexType element cannot be used to create a new complex type by restriction.

A Schema for a Data-Oriented XML Document

The example that has been used up to this point has been a document-oriented XML document with no data types besides string. To see how the other data types work, in this section we'll create an example using the Northwind Traders database. (This database can be found in Microsoft Access, Visual Studio, and Microsoft SQL Server 7.) For the Customer and Categories tables, you could create the schema shown below.

 <?xml version ="1.0"?> <schema targetNamespace = "http://www.northwind.com/Category"     xmlns = http://www.w3.org/1999/XMLSchema     xmlns:Categories = "http://www.northwind.com/Category"> <simpleType name="String15" source="string"         <maxLength= "15" />         <minLength = "0"/>     </simpleType>     <simpleType name="String5" base="string">         <maxLength= "5"/ >         <minLength = "0"/>     </simpleType>     <simpleType name="String30" base="string">         <maxLength= "30" />         <minLength = "0"/>     </simpleType>     <simpleType name="String60" base="string">         <maxLength= "60" />         <minLength = "0"/>     </simpleType>    <simpleType name="String10" base="string">         <maxLength= "10" />         <minLength = "0"/>     </simpleType>     <simpleType name="String24" base="string">         <maxLength= "24" />         <minLength = "0"/>     </simpleType>    <simpleType name="String40" base="string">         <maxLength= "40" />         <minLength = "0"/>     </simpleType>     <element name = "Categories">         <complexType content = "elementOnly">             <group>             <sequence>             <element ref = "Categories.CategoryID"                       minOccurs = "1" maxOccurs = "1" />             <element ref = "Categories.CategoryName"                       minOccurs = "1" maxOccurs = "1" />             <element ref = "Categories.Description"                       minOccurs = "0" maxOccurs = "1" />             <element ref = "Categories.Picture" minOccurs = "0"                       maxOccurs = "1"/>             </sequence>             </group>         </complexType>     </element>     <element name = "Categories.CategoryID" type = "integer">         <annotation>             <documentation>Number automatically assigned to a new                            category             </documentation>         </annotation>     </element>     <element name = "Categories.CategoryName" type = "String15">         <annotation>             <documentation>Name of food category</documentation>         </annotation>     </element>     <element name = "Categories.Description" type = "string"/>     <element name = "Categories.Picture" type = "binary">         <annotation>             <documentation> Picture representing the food category             </documentation>         </annotation>     </element>     <element name = "Customers">         <complexType content = "elementOnly">             <group>                 <sequence>                     <element ref = "Customers.CustomerID"                              minOccurs = "1" maxOccurs = "1"/>                     <element ref = "Customers.CompanyName"                               minOccurs = "1" maxOccurs = "1"/>                     <element ref = "Customers.ContactName"                               minOccurs = "1" maxOccurs = "1"/>                     <element ref = "Customers.ContactTitle"                               minOccurs = "0" maxOccurs = "1"/>                     <element ref = "Customers.Address"                               minOccurs = "1" maxOccurs = "1"/>                     <element ref = "Customers.City" minOccurs = "1"                               maxOccurs = "1"/>                     <element ref = "Customers.Region"                               minOccurs = "1" maxOccurs = "1"/>                     <element ref = "Customers.PostalCode"                               minOccurs = "1" maxOccurs = "1"/>                     <element ref = "Customers.Country"                               minOccurs = "1" maxOccurs = "1"/>                     <element ref = "Customers.Phone" minOccurs = "1"                              maxOccurs = "1"/>                     <element ref = "Customers.Fax" minOccurs = "0"                               maxOccurs = "1"/>                 </sequence>             </group>         </complexType>     </element>     <element name = "Customers.CustomerID" type = "CustomerIDField">         <annotation>             <documentation>                 Unique five-character code based on customer name             </documentation>         </annotation>     </element>     <element name = "Customers.CompanyName" type = "String5"/>     <element name = "Customers.ContactName" type = "String40"/>     <element name = "Customers.ContactTitle" type = "String30"/>     <element name = "Customers.Address" type = "String60">         <annotation>             <documentation>Street or post-office box</documentation>         </annotation>     </element>     <element name = "Customers.City" type = "String15"/>     <element name = "Customers.Region" type = "String15">         <annotation>             <documentation>State or province</documentation>         </annotation>     </element>     <element name = "Customers.PostalCode" type = "String10"/>     <element name = "Customers.Country" type = "String15"/>     <element name = "Customers.Phone" type = "String24">         <annotation>             <documentation>                 Phone number includes country code or area code             </documentation>         </annotation>     </element>     <element name = "Customers.Fax" type = "String24">         <annotation>             <documentation>                 Fax number includes country code or area code             </documentation>         </annotation>     </element> </schema> 

Notice that Categories and Customers have been used as prefixes to identify what objects the elements belong to. If you look in the Northwind Traders database, you'll see that the field data types and the lengths for character data types match those in the database. The comments that were included in the Northwind Traders database were also used in the schema. You can see that it's fairly easy to convert a database table into a schema.

Now that we have discussed schemas, we'll need to cover namespaces and schemas. In the following section, we'll examine how to use namespaces in schemas.



Developing XML Solutions
Developing XML Solutions (DV-MPS General)
ISBN: 0735607966
EAN: 2147483647
Year: 2000
Pages: 115
Authors: Jake Sturm

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net