2.5 Element ContentElement Content
The purchase order schema has many examples of elements
containing other elements (e.g. items),
elements having attributes and containing other elements
(e.g. shipTo), and elements containing only a
simple type of value (e.g. USPrice). However,
we have not seen an element having attributes but
containing only a simple type of value, nor have we seen an
element that contains other elements mixed with character
content, nor have we seen an element that has no content at
all. In this section we'll examine these variations in the
content models of elements.
Complex Types from Simple Types[top]
Complex Types from Simple Types
Let us first consider how to declare an element that has
an attribute and contains a simple value. In an instance
document, such an element might appear as:
NOTE:
<internationalPrice currency="EUR">423.46</internationalPrice>
The purchase order schema declares a USPrice
element that is a starting point:
NOTE:
<xsd:element name="USPrice" type="decimal"/>
ref37Now, how do we add an attribute to
this element? As we have said before, simple types cannot
have attributes, and
decimal is a simple type. Therefore, we must
define a complex type to carry the attribute declaration.
We also want the content to be simple type decimal. So our original question
becomes: How do we define a complex type that is based on
the simple type
decimal? The answer is to derive a new
complex type from the simple type
decimal:
NOTE:
Deriving a Complex Type from a Simple Type
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:decimal">
<xsd:attribute name="currency" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
We use the
complexType element to start the definition of a
new (anonymous) type. To indicate that the content model of
the new type contains only character data and no elements,
we use a
simpleContent element. Finally, we derive the
new type by extending the simple
decimal type. The extension consists of adding a
currency attribute using a standard attribute
declaration. (We cover type derivation in detail in [Advanced Concepts II: The International Purchase Order].) The
internationalPrice element declared in this way will
appear in an instance as shown in the example at the
beginning of this section.
Mixed Content[top]
Mixed Content
ref51The construction of the purchase order schema may be
characterized as elements containing subelements, and the
deepest subelements contain character data. XML Schema also
provides for the construction of schemas where character
data can appear alongside subelements, and character data
is not confined to the deepest subelements.
To illustrate, consider the following snippet from a
customer letter that uses some of the same elements as the
purchase order:
NOTE:
Snippet of Customer Letter
<letterBody>
<salutation>Dear Mr.<name>Robert Smith</name>.</salutation>
Your order of <quantity>1</quantity> <productName>Baby
Monitor</productName> shipped from our warehouse on
<shipDate>1999-05-21</shipDate>. ....
</letterBody>
Notice the text appearing between elements and their child
elements. Specifically, text appears between the elements
salutation, quantity,
productName and shipDate which are all
children of letterBody, and text appears
around the element namename
which is the child of a child of
letterBody. The following snippet of a schema
declares letterBody:
NOTE:
Snippet of Schema for Customer Letter
<xsd:element name="letterBody">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="salutation">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="quantity" type="xsd:positiveInteger"/>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
<!-- etc. -->
</xsd:sequence>
</xsd:complexType>
</xsd:element>
The elements appearing in the customer letter are
declared, and their types are defined using the element and complexType element
constructions we have seen before. To enable character data
to appear between the child-elements of
letterBody, the
mixed attribute on the type definition is set to
true.
Note that the mixed model in XML Schema
differs fundamentally from the
mixed model in XML 1.0. Under the XML Schema
mixed model, the order and number of child elements
appearing in an instance must agree with the order and
number of child elements specified in the model. In
contrast, under the XML 1.0 mixed model, the order and
number of child elements appearing in an instance cannot be
constrained. In summary, XML Schema provides full validation of
mixed models in contrast to the partial schema validation
provided by XML 1.0.
Empty Content[top]
Empty Content
Now suppose that we want the
internationalPrice element to convey both the unit
of currency and the price as attribute values rather than
as separate attribute and content values. For example:
NOTE:
<internationalPrice currency="EUR" value="423.46"/>
ref13Such an element has no content at
all; its content model is empty. To define a type whose
content is empty, we essentially define a type that allows
only elements in its content, but we do not actually
declare any elements and so the type's content model is
empty:
NOTE:
An Empty Complex Type
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:complexContent>
<xsd:restriction base="xsd:anyType">
<xsd:attribute name="currency" type="xsd:string"/>
<xsd:attribute name="value" type="xsd:decimal"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
In this example, we define an (anonymous) type having
complexContent, i.e. only elements. The
complexContent element signals that we intend to
restrict or extend the content model of a complex type, and the
restriction of anyType declares
two attributes but does not introduce any element content
(see [Deriving Complex Types by Restriction] for more
details on restriction). The
internationalPrice element declared in this way may
legitimately appear in an instance as shown in the example
above.
The preceding syntax for an empty-content element is
relatively verbose, and it is possible to declare the
internationalPrice element more compactly:
NOTE:
Shorthand for an Empty Complex Type
<xsd:element name="internationalPrice">
<xsd:complexType>
<xsd:attribute name="currency" type="xsd:string"/>
<xsd:attribute name="value" type="xsd:decimal"/>
</xsd:complexType>
</xsd:element>
This compact syntax works because a complex type defined
without any simpleContent or
complexContent is interpreted as shorthand for
complex content that restricts anyType.
anyType
The anyType represents an abstraction called
the [
ur-type] which is the base type from which all
simple and complex types are derived. An
anyType type does not constrain its content in any
way. It is possible to use anyType like other
types, for example:
NOTE:
<xsd:element name="anything" type="xsd:anyType"/>
The content of the element declared in this way is
unconstrained, so the element value may be 423.46, but it
may be any other sequence of characters as well, or indeed
a mixture of characters and elements. In fact,
anyType is the default type when none is specified,
so the above could also be written as follows:
NOTE:
<xsd:element name="anything"/>
If unconstrained element content is needed, for example in
the case of elements containing prose which requires embedded
markup to support internationalization, then the default
declaration or a slightly restricted form of it may be suitable.
The text type described in [Any Element, Any Attribute]
is an example of such a type that is suitable for such
purposes.
|