Let's see where we can use our Swiss army knife in our library. The first datatype, which we promised to improve at the end of the last chapter, is the ISBN number. Without fiddling the details of the constitution of an ISBN number (which can't be fully checked with W3C XML Schema), we can check that the total number of characters actually used is 10 and limit its contents to digits and the letter "X.":
<xs:simpleType name="isbn"> <xs:restriction base="xs:NMTOKEN"> <xs:length value="10"/> <xs:pattern value="[0-9]{9}[0-9X]"/> </xs:restriction> </xs:simpleType>
TIP: You may wonder why we kept the xs:length, since as far as validation is concerned, it is less constraining than the xs:pattern that we added. This is a question worth asking, but it doesn't have a complete answer yet. However, applications which use the PSVI as a source of meta information may or may not be able to deduce from a pattern that the length of a string has been fixed. It might be good practice to keep redundant facets to provide extra information to these future applications.
W3C XML Schema doesn't allow expression of the fact that the book ID is the same value as the ISBN number with a "b" used as a prefix, but we can still define that it is a "b" with 9 digits and a trailing digit or "X":
<xs:simpleType name="bookID"> <xs:restriction base="xs:ID"> <xs:pattern value="b\[0-9]{9}[0-9X]"/> </xs:restriction> </xs:simpleType>
To use this new datatype, we must be aware that we are using a global attribute that was referenced in the element book, but that was also referenced in the elements character and author, which do not have the same format. This is the main limitation in using global elements and attributes: they can be referenced only if they have the same types at all the locations in which they appear. We can work around this problem by creating a local attribute definition for the id attribute of book with the new datatype.
The last things we may want to constrain are the dates for which no time zones are needed and which, in fact, could just be a potential source of issues if we need to compare them:
<xs:simpleType name="date"> <xs:restriction base="xs:date"> <xs:pattern value="[^:Z]*"/> </xs:restriction> </xs:simpleType>
Our new schema is then:
<?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:simpleType name="string255"> <xs:restriction base="xs:token"> <xs:maxLength value="255"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="string32"> <xs:restriction base="xs:token"> <xs:maxLength value="32"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="isbn"> <xs:restriction base="xs:NMTOKEN"> <xs:length value="10"/> <xs:pattern value="[0-9]{9}[0-9X]"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="bookID"> <xs:restriction base="xs:ID"> <xs:pattern value="b\d[0-9]{9}[0-9X]"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="supportedLanguages"> <xs:restriction base="xs:language"> <xs:enumeration value="en"/> <xs:enumeration value="es"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="date"> <xs:restriction base="xs:date"> <xs:pattern value="[^:Z]*"/> </xs:restriction> </xs:simpleType> <xs:element name="name" type="string32"/> <xs:element name="qualification" type="string255"/> <xs:element name="born" type="date"/> <xs:element name="dead" type="date"/> <xs:element name="isbn" type="isbn"/> <xs:attribute name="id" type="xs:ID"/> <xs:attribute name="available" type="xs:boolean"/> <xs:attribute name="lang" type="supportedLanguages"/> <xs:element name="title"> <xs:complexType> <xs:simpleContent> <xs:extension base="string255"> <xs:attribute ref="lang"/> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element> <xs:element name="library"> <xs:complexType> <xs:sequence> <xs:element ref="book" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="author"> <xs:complexType> <xs:sequence> <xs:element ref="name"/> <xs:element ref="born"/> <xs:element ref="dead" minOccurs="0"/> </xs:sequence> <xs:attribute ref="id"/> </xs:complexType> </xs:element> <xs:element name="book"> <xs:complexType> <xs:sequence> <xs:element ref="isbn"/> <xs:element ref="title"/> <xs:element ref="author" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="character" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="id" type="bookID"/> <xs:attribute ref="available"/> </xs:complexType> </xs:element> <xs:element name="character"> <xs:complexType> <xs:sequence> <xs:element ref="name"/> <xs:element ref="born"/> <xs:element ref="qualification"/> </xs:sequence> <xs:attribute ref="id"/> </xs:complexType> </xs:element> </xs:schema>
Copyright © 2002 O'Reilly & Associates. All rights reserved.