- Introducing Datatypes
- Primitive Datatypes
- Constraining Facets
- Built-in Derived Datatypes
- Defining Your Own Datatypes
Defining Your Own Datatypes
While the primitive and built-in derived datatypes are very handy, the real power of datatypes in XML Schemas is expressed in the ability to create your own datatypes. You can create both simpleType and complexType datatypes, and you can derived them by extension or restriction.
You've already seen one example of creating a type by restriction, our dollar example. We used the <simpleType> element to create our new simple type:
<xs:simpleType name="dollar"> <xs:restriction base="decimal"> <xs:fractionDigits value="2"/> </xs:restriction> </xs:simpleType>
Once that type is defined, we can even create a new type, based on the dollar type, which is also a restriction. Simple types can only be restricted; you can't use an extension with a simple type. So we could create a new type to further restrict the value of the dollar type:
<xs:simpleType name="price"> <xs:restriction base="dollar"> <xs:minInclusive value="4.99"/> <xs:maxInclusive value="9.99"/> </xs:restriction> </xs:simpleType>
This creates a new type called price, which can have any decimal value with two decimal places ranging from 4.99 to 9.99. So 8.87 would be a valid value, while 3.99 or 14.89 would not.
Similarly, we could use the restriction mechanism to create an enumeration; for example, to create an element for sizes, but limit the choices:
<xs:simpleType name="size"> <xs:restriction base="xs:string"> <xs:enumeration value="small"/> <xs:enumeration value="medium"/> <xs:enumeration value="large"/> <xs:enumeration value="x-large"/> </xs:restriction> </xs:simpleType>
As you can see, deriving new simple types by restriction can be quite straightforward. Of course, we can also create our own complex types:
<xs:complexType name="contact"> <xs:complexContent> <xs:element name="name" type="xs:string"/> <xs:element name="address" type="xs:string"/> <xs:element name="city" type="xs:string"/> <xs:element name="state" type="xs:string"/> <xs:element name="zip" type="xs:string"/> </xs:complexContent> </xs:complexType>
We can then use this type to declare an element:
<xs:element name="customer" type="contact"/>
The reason for defining the contact as a type rather than as an element in the first place is that this method provides the ability to reuse the content with any number of elements. And now we can extend this type as well. For example, let's say we wanted to add phone numbers to the contact type. We could create a new type, which would be an extension of the original type:
<xs:complexType name="customer-contact"> <xs:complexContent> <xs:extension base="contact"> <xs:element name="phone" type="xs:string"/> <xs:element name="fax" type="xs:string"/> <xs:element name="email" type="xs:string"/> </xs:complexContent> </xs:complexType>
Now we have a new type, called customer-contact, which, if we declared it as an element,
<xs:element name="customer" type="customer-contact"/>
would have a corresponding XML instance document that looked like this:
<customer-contact> <name>Jane Doe</name> <address>10 W. Ontario</address> <city>Chicago</city> <state>IL</state> <zip>60647</zip> <phone>312-555-1234</phone> <fax>312-555-1212</fax> <email>jane@doe.com</email> </customer-contact>
which contains both the elements from our original contact type, and the new elements we added when we extended the type to create the customer-contact type.
As you can see, we've only begun to scratch the surface of what can be accomplished using datatypes with your XML Schemas. Datatyping is one of the most significant improvements to XML Schemas over Document Type Definitions. Mastering datatypes can seem complicated, but once the task is mastered, it adds a new level of control to your XML documents that simply was impossible before.