Most of the types that I've used in book.xsd are simple types that come built into the XML schema specification, such as xsd:string, xsd:integer, xsd:date, and so on. However, take a look at the attribute named bookID—this attribute is declared to be of the type catalogID:
<xsd:complexType name="books"> <xsd:element name="book" minOccurs="0" maxOccurs="10"> <xsd:complexType> <xsd:element name="bookTitle" type="xsd:string"/> <xsd:element name="pubDate" type="xsd:date" minOccurs='0'/> <xsd:element name="replacementValue" type="xsd:decimal"/> <xsd:element name="maxDaysOut"> <xsd:simpleType base="xsd:integer"> <xsd:maxExclusive value="14"/> </xsd:simpleType> </xsd:element> <xsd:attribute name="bookID" type="catalogID"/> </xsd:complexType> </xsd:element> </xsd:complexType>
This type, catalogID, is itself a simple type that is not built into the XML schema specification; instead, I've defined it with the <simpleType> element, like this:
<xsd:complexType name="books"> <xsd:element name="book" minOccurs="0" maxOccurs="10"> <xsd:complexType> <xsd:element name="bookTitle" type="xsd:string"/> <xsd:element name="pubDate" type="xsd:date" minOccurs='0'/> <xsd:element name="replacementValue" type="xsd:decimal"/> <xsd:element name="maxDaysOut"> <xsd:simpleType base="xsd:integer"> <xsd:maxExclusive value="14"/> </xsd:simpleType> </xsd:element> <xsd:attribute name="bookID" type="catalogID"/> </xsd:complexType> </xsd:element> </xsd:complexType> <xsd:simpleType name="catalogID" base="xsd:string"> <xsd:pattern value="d{3}-d{4}-d{3}"/> </xsd:simpleType>
Note in particular that you must base new simple types such as catalogID on already existing simple type (either a built-in simple type or one that you've created; here, I'm using the built-in xsd:string type). To do that, you use the base attribute in the <xsd:simpleType> element. In the case of the catalogID type, I've based it on the xsd:string type with the attribute/value pair base="xsd:string". To describe the properties of new simple types, XML schemas use facets, which are discussed in the next section.
Using facets lets you restrict the data that a simple type can hold. For example, say that you want to create a simple type named dayOfMonth that can hold only values between 1 and 31, inclusive. In that case, you can define it this way, using the two facets minInclusive and maxInclusive:
<xsd:simpleType name="dayOfMonth" base="xsd:integer"> <xsd:minInclusive value="1"/> <xsd:maxInclusive value="31"/> </xsd:simpleType>
Now that you've created this new simple type, you can declare elements and attributes of this type.
In book.xsd, the catalogID simple type is even more powerful than this dayOfMonth simple type. The catalogID simple type uses the pattern facet to specify a regular expression (that is, a pattern set up to match text in the format that you specify) that text strings values for this type must satisfy:
<xsd:simpleType name="catalogID" base="xsd:string"> <xsd:pattern value="d{3}-d{4}-d{3}"/> </xsd:simpleType>
In this case, the text in the simpleType type must match the regular expression "d{3}-d{4}-d{3}", which stands for three digits, a hyphen, four digits, another hyphen, and three digits.
About Regular ExpressionsThe regular expressions used in XML schema facets are the same as those used in the Perl programming language. You can find the complete documentation for Perl regular expressions at the Comprehensive Perl Archive Network (CPAN) Web site: http://www.cpan.org/doc/manual/html/pod/perlre.html. (Regular expressions are not a skill that you'll need in this book.) |
The catalogID type is the type of the <book> element's bookID attribute, so I can specify book ID values like this in book.xml, matching the regular expression that I've used for this attribute:
<book bookID="123-4567-890"> <bookTitle>Earthquakes for Breakfast</bookTitle> <pubDate>2001-10-20</pubDate> <replacementValue>15.95</replacementValue> <maxDaysOut>14</maxDaysOut> </book>
What facets are there, and what built-in simple types support them? You'll find the seven general facets, listed by the simple types that support them, in Table 5.3.
The numeric simple types, and those simple types that can be ordered, also have some additional facets, which you see in Tables 5.4 and 5.5.
Some additional facets that have to do with dates and times apply to simple types, and you'll find them in Table 5.6.
Type | Period | Duration |
---|---|---|
century | x | x |
date | x | x |
month | x | x |
recurringDate | x | x |
recurringDay | x | x |
recurringDuration | x | x |
time | x | x |
timeDuration | x | x |
timeInstant | x | x |
timePeriod | x | x |
year | x | x |
Of all the facets that you see in Tables 5.3, 5.4, and 5.5, my favorites are minInclusive, maxInclusive, pattern, and enumeration. We've seen the first three, but not the enumeration facet yet.
The enumeration facet lets you set up an enumeration of values, exactly as you can do in DTDs (as we saw in the previous chapter). Using an enumeration, you can restrict the possible values of a simple type to a list of values that you specify.
For example, to set up a simple type named weekday whose values can be "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", and "Saturday", you'd define that type like this:
<xsd:simpleType name="weekday" base="xsd:string"> <xsd:enumeration value="Sunday"/> <xsd:enumeration value="Monday"/> <xsd:enumeration value="Tuesday"/> <xsd:enumeration value="Wednesday"/> <xsd:enumeration value="Thursday"/> <xsd:enumeration value="Friday"/> <xsd:enumeration value="Saturday"/> </xsd:simpleType>
So far, all the element declarations that we've used in the book.xsd schema have used the type attribute to indicate the new element's type. But what if you want to use a type only once? Do you have to go to the trouble of declaring it and naming it, all to use it in only one element declaration?
It turns out that there is an easier way. You can use an anonymous type definition to avoid having to define a whole new type that you'll reference only once. Using an anonymous type definition simply means that you enclose the <xsd:simpleType> or <xsd:complexType> element inside the <xsd:element> element declaration. In this case, you don't assign an explicit value to the type attribute in the <xsd:element> element because the anonymous type that you're using doesn't have a name. (In fact, you can tell that an anonymous type definition is being used if the <xsd:complexType> element doesn't include a type attribute.)
Here's an example from book.xsd; in this case, I'll use an anonymous type definition for the <book> element. This element holds <bookTitle>, <pubDate>, <replacementValue>, and <maxDaysOut> elements. It will also have an attribute named bookID, so it looks like a good one to create from a complex type. Instead of declaring a separate complex type, however, I'll just put the <xsd:complexType> element inside the <xsd:element> element that declares <book>:
<xsd:element name="book" minOccurs="0" maxOccurs="10"> <xsd:complexType> . . . </xsd:complexType> </xsd:element>
Now I'm free to add the elements that I want inside the <book> element—without defining a named, separate complex type at all:
<xsd:element name="book" minOccurs="0" maxOccurs="10"> <xsd:complexType> <xsd:element name="bookTitle" type="xsd:string"/> <xsd:element name="pubDate" type="xsd:date" minOccurs='0'/> <xsd:element name="replacementValue" type="xsd:decimal"/> . . . </xsd:complexType> </xsd:element>
You can also use simple anonymous types; for example, the <maxDaysOut> element holds the maximum number of days that a book is supposed to be out. To set the maximum number of days that a book can be out to 14, I use a new simple anonymous type so that I can use the maxExclusive facet, like this:
<xsd:element name="book" minOccurs="0" maxOccurs="10"> <xsd:complexType> <xsd:element name="bookTitle" type="xsd:string"/> <xsd:element name="pubDate" type="xsd:date" minOccurs='0'/> <xsd:element name="replacementValue" type="xsd:decimal"/> <xsd:element name="maxDaysOut"> <xsd:simpleType base="xsd:integer"> <xsd:maxExclusive value="14"/> </xsd:simpleType> </xsd:element> . . . </xsd:complexType> </xsd:element>
You can also include attribute declarations in anonymous type definitions, like this:
<xsd:element name="book" minOccurs="0" maxOccurs="10"> <xsd:complexType> <xsd:element name="bookTitle" type="xsd:string"/> <xsd:element name="pubDate" type="xsd:date" minOccurs='0'/> <xsd:element name="replacementValue" type="xsd:decimal"/> <xsd:element name="maxDaysOut"> <xsd:simpleType base="xsd:integer"> <xsd:maxExclusive value="14"/> </xsd:simpleType> </xsd:element> <xsd:attribute name="bookID" type="catalogID"/> </xsd:complexType> </xsd:element>
3.22.77.149