In many cases, it is useful to declare an element that cannot contain anything. Most of these elements convey all of their information via attributes or simply by their position in relation to other elements (e.g., the br element from XHTML).Let's add a contact-information element to the address element that will be used to contain a list of ways to contact a person. Example 17-8 shows the sample instance document after adding the new contacts element and a sample phone entry.
Example 17-8. addressdoc.xml with contact element
<?xml version="1.0"?> <addr:address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://namespaces.oreilly.com/xmlnut/address address-schema.xsd" xmlns:addr="http://namespaces.oreilly.com/xmlnut/address" addr:language="en"> <addr:fullName> <addr:first>William</addr:first> <addr:middle>Scott</addr:middle> <addr:last>Means</addr:last> </addr:fullName> <addr:contacts> <addr:phone addr:number="888.737.1752"/> </addr:contacts> </addr:address>
Supporting this new content requires further modifications to the schema document. Although it would be possible to declare the new element inline within the existing address-element declaration, for clarity it makes sense to create a new global type and reference it by name :
<xs:element name="address"> <xs:complexType> <xs:sequence> <xs:element name="fullName"> . . . </xs:element> <xs:element name="contacts" type="addr:contactsType" minOccurs="0"/> </xs:sequence> <xs:attributeGroup ref="addr:nationality"/> </xs:complexType> </xs:element>
The declaration for the new contactsType complex type looks like this:
<xs:complexType name="contactsType"> <xs:sequence> <xs:element name="phone" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:attribute name="number" type="xs:string"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType>
The syntax used to declare an empty element is actually very simple. Notice that the xs:element declaration for the previous phone element contains a complex type definition that only includes a single attribute declaration. This tells the schema processor that the phone element may only contain complex content (elements), and since no additional nested element declarations are provided, it must remain empty.
17.5.1 The complexContent Element
The preceding example actually took a shortcut with the schema language. One of the early fullName element declarations used the xs:simpleContent element to indicate that the element could only contain simple content (no nested elements). There is a corresponding content-declaration element that specifies that a complex type can only contain complex content (elements). This is the xs:complexContent element.
When the phone element was declared using an xs:complexType element with no nested element declarations, the schema processor automatically inferred that it should contain only complex content. The phone element declaration could be rewritten like so, using the xs:complexContent element:
<xs:element name="phone" minOccurs="0"> <xs:complexType> <xs:complexContent> <xs:restriction base="xs:anyType"> <xs:attribute name="number" type="xs:string"/> </xs:restriction> </xs:complexContent> </xs:complexType> </xs:element>
The most common reason to use the xs:complexContent element is to derive a complex type from an existing type. This example derives a new type by restriction from the built-in xs:anyType type. xs:anyType is the root of all of the built-in schema types and represents an unrestricted sequence of characters and markup. Since the xs:complexType indicates that the element can only contain element content, the effect of this restriction is to prevent the element from containing either character data or markup.