home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeXML SchemaSearch this book

12.2. Controlling Derivations

It's time to come back to the features already discussed--and to introduce new ones--to explain how to control the usage of the derivations of the different compositors. Basically, these features are attributes that allow you to block further derivation or, on the contrary, allow you to require derivations, but their granularity varies depending on the compositor being used.

12.2.1. Attributes

There are no substitution groups for attributes and no mechanism to derive them or define their types in instance documents. This also means no features are needed to control their derivation. Actually, to be completely accurate, we need to note that it is possible to indirectly derive attributes through a derivation by restriction of their parent elements or redefinitions of attribute groups.

12.2.2. Elements

When speaking of a xs:element, we need to differentiate between global definitions and local definitions or references that behave differently in regard to derivation. Therefore, derivation control is maintained as shown in Table 12-2.

Table 12-2. Controls on element derivation

Attribute

Global element

Local element definition

Element reference

block

Yes

Yes

No

abstract

Yes

No

No

final

Yes

No

No

12.2.2.1. Block attribute

The block attribute controls type substitution in the instance documents through the xsi:type attribute and substitution groups. This single attribute holds a whitespace-separated list of tokens-- of "restriction," "extension," and "substitution"--or the special value #all (which means all three values together and the attribute's default value can be defined through the blockDefault attribute of the xs:schema document element).

The first two values (restriction and extension) control any substitution through xsi:type or substitution groups, and block the substitution by datatypes that are derived by restriction or extension from the datatype defined in the element declaration. The third (substitution) is specific to the substitution groups, and defines if an element from the substitution group (for which the element is the head) is allowed. Since only global elements can participate in a substitution group, the last value is clearly meaningful for global definitions only.

The fact that the block attribute is used both for type substitution and for substitution groups can be misleading, especially with the values restriction and extension, which act on both aspects. A simple example makes this more concrete. Let's say that we have a complex type definition (personType) describing a person as having a name, a mandatory birth date, and optional death date and qualification:

<xs:complexType name="personType">
  <xs:sequence>
    <xs:element ref="name"/>
    <xs:element ref="born"/>
    <xs:element ref="dead" minOccurs="0"/>
    <xs:element ref="qualification" minOccurs="0"/>
  </xs:sequence>
  <xs:attribute ref="id"/>
</xs:complexType>

We can also derive by extension from this complex type a datatype that describes an author as a person with a list of books:

<xs:complexType name="authorType">
  <xs:complexContent>
    <xs:extension base="personType">
      <xs:sequence> 
        <xs:element name="book" type="xs:token" minOccurs="1"
          maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

We can derive by restriction a datatype that describes a character as a person with no death date and a mandatory qualification:

<xs:complexType name="characterType">
  <xs:complexContent>
    <xs:restriction base="personType">
      <xs:sequence>
        <xs:element ref="name"/>
        <xs:element ref="born"/>
        <xs:element ref="qualification"/>
      </xs:sequence>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

The first purpose of block attributes in element definitions is to control the type substitution through xsi:type, which controls substitutions in the instance documents such as the following (if the person element is defined as having a type personType):

<person xsi:type="authorType" id="CMS"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <name>
    Charles M Schulz
  </name>
  <born>
    1922-11-26
  </born>
  <dead>
    2000-02-12
  </dead>
  <book>
    Being a Dog Is a Full-Time Job
  </book>
</person>
               
<person xsi:type="characterType" id="Snoopy"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <name>
    Snoopy
  </name>
  <born>
    1950-10-04
  </born>
  <qualification>
    extroverted beagle
  </qualification>
</person>

The first substitution uses authorType, which is derived by extension from personType, and can be blocked by specifying a block attribute including the value extension. The second one uses characterType, which is derived by restriction from personType and can be blocked by specifying a block attribute including the value restriction. Both can be blocked together by specifying a block attribute with the value #all.

TIP: This example shows that the impact of both derivation types on the applications is very different. A type substitution by restriction has virtually no impact on the applications, since the content model matching the restricted type must also match the original type. Alternatively, a type substitution by extension allows content models not allowed by the original type (such as the addition of the book element in the previous example), and the risk of breaking applications that do not expect these additions is higher. Thus, a conservative attitude might be to include extension in the default values of block in your schemas.

That being said, we've seen only one side of the block attribute. It serves a second, different, yet not independent, purpose and also restricts the usage of substitution groups. To illustrate this purpose, let's define three different element members of a substitution group whose head is person. There is also a fourth element member, which is just a synonym for the element person and has the same type:

<xs:element name="person" type="personType"/>
              
<xs:element name="author" type="authorType"
  substitutionGroup="person"/>
              
<xs:element name="character" type="characterType"
  substitutionGroup="person"/>
              
<xs:element name="human" type="personType"
  substitutionGroup="person"/>

After defining this substitution group and without blocking anything, we allow not only block and the type substitutions seen above, but also element substitutions, such as:

<author id="CMS">
  <name>
    Charles M Schulz
  </name>
  <born>
    1922-11-26
  </born>
  <dead>
    2000-02-12
  </dead>
  <book>
    Being a Dog Is a Full-Time Job
  </book>
</author>
              
<character id="PP">
  <name>
    Peppermint Patty
  </name>
  <born>
    1966-08-22
  </born>
  <qualification>
    bold, brash and tomboyish
  </qualification>
</character>
<human id="CMS.">
  <name>
    Charles M Schulz
  </name>
  <born>
    1922-11-26
  </born>
  <dead>
    2000-02-12
  </dead>
</human>

The first substitution is by an element of the substitution group whose type is derived by extension from the head. It can be blocked by specifying a block attribute including the value extension. The second one is a substitution by an element of the substitution group whose type is derived by restriction from the head. It can be blocked by specifying a block attribute including the value restriction. Those two are similar to the two substitutions given as examples for the type substitutions, with the difference that the element name is now used to differentiate the type instead of the xsi:type attribute. The third substitution is new, since the type is the same as the type of the head, and it is blocked only by specifying a block attribute that includes the value substitution. Note that including substitution in a block attribute blocks any element substitution, while stating that not all the combinations are possible to express. To block everything, you would define author as:

<xs:element name="author" type="authorType" block="#all"/>

I don't want to leave you with the impression than you can't block type substitution without blocking substitution groups. We need to mention that type substitution can also be blocked on complex type definitions, which is covered later on in this chapter in Section 12.2.3, "Complex Types".

12.2.2.2. Final elements

Like block, final has an impact on substitution groups, but works on a different level: constraining the schema itself while block constrains the instance documents. final can take a list of restriction and extension or the special value #all, and its default value can be defined using the finalDefault attribute of xs:schema. However, a substitution value is not necessary, since unlike block, final is about substitution groups, and #all can block all the substitutions (and only the substitutions).

final's effect is more radical than block: while block blocks the effects of the usage of substitution groups, final prohibits the usage of the element as a head of a substitution group. If the person element is defined with a final attribute set, it isn't possible to use it as head of a substitution group for either author, character, or both.

12.2.3. Complex Types

The attributes are the same for complex types as they are for elements, but their meaning is slightly different since one of them (block) operates on the substitution of the elements that use the datatype (as we have seen in the previous section). The others (final and abstract) work on the derivation of the complex type itself.

12.2.3.1. Blocking complex types

When the block attribute is used on complex type definitions, the type substitutions in the elements defined with this type are still blocked. The difference is that this time block doesn't act on element substitutions through substitution groups, but it does act on type substitutions. These block attributes can be seen as electric switches installed in a series, and each of them can block the derivation in its own "line," as shown in Figure 12-1.

Figure 12-1

Figure 12-1. Block attribute on elements and complex type definitions

For each restriction and extension, the substitutions can first be switched off for both element and type substitutions by the block attribute of the element definition, and then the type substitutions can be blocked by the block attribute of the complex type definition. The value substitution in the block attribute of the element definition acts as a global switch to block all element substitutions, including a third line, which allows element substitutions with the same type and cannot be blocked separately.

The default value supplied in the schema element is used at both levels and may be different for the element and complex type definitions if they belong to different schemas and have a different xs:schema ancestor. The fact that the default value, when defined in the xs:schema ancestor, is applied to both levels means that it may block the derivation for those to levels (by "opening" two switches). To override such a nonempty default value, you need to define a block attribute both in the element and in the complex type definition.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.