Chapter 15. Named groups

XML Schema provides the ability to define groups of element and attribute declarations that are reusable by many complex types. Named model groups are fragments of content models, and attribute groups are bundles of attribute declarations that are commonly used together. This chapter explains how to define and reference named model groups and attribute groups.

15.1. Why named groups?

Defining a group and reusing it many times has the advantages of

• Encouraging consistency across schema components

• Allowing the schema author to change multiple content models in only one place

• Making it obvious that certain complex types share similar children or attributes

• In many cases, making the schema less verbose

15.2. Named model groups

Named model groups are reusable fragments of content models. For example, if there are many type definitions in your schema that specify a description, optionally followed by a comment, you could define a group that represents this content model fragment. The group could then be used by many complex type definitions. Named model groups cannot contain attribute declarations; that is the purpose of attribute groups, which are described in Section 15.3 on p. 392.

A note on terminology: XML Schema formally uses the term “model group definition” for group elements, and “model group” for all, choice, and sequence groups. In this book, group elements are referred to as “named model groups” to reduce confusion associated with the two similar terms.

15.2.1. Defining named model groups

Named model groups are represented by group elements whose syntax is shown in Table 15–1. Named model groups are required to have a name, and that name must be unique among all the named model groups in the schema. Named model groups are always defined globally, meaning that their parent is always schema.1

Table 15–1. XSD Syntax: named model group definition

Image

Named model groups may contain any content model. However, a group cannot contain an element directly. Instead, group must have one and only one model group (choice, sequence, or all) as a child. There is an additional constraint that this one model group child cannot have occurrence constraints (minOccurs and maxOccurs) like other model groups. If you wish to indicate that the contents of the group appear multiple times, you may put occurrence constraints on the group reference, as described in Section 15.2.2.1 on p. 388.

Example 15–1 shows the definition of a named model group that contains a description optionally followed by a comment. Note that the group has one child, a sequence, which has no occurrence constraints on it.

Example 15–1. Named model group with local element declarations


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:group name="DescriptionGroup">
    <xs:sequence>
      <xs:element name="description" type="xs:string"/>
      <xs:element name="comment" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:group>
</xs:schema>


In Example 15–1, the element declarations are local in the group, as evidenced by the appearance of a name attribute instead of a ref attribute. It is also possible to use global element declarations, and then reference them from the named model group, as shown in Example 15–2.

Note that the type attribute is now in the global element declaration, while minOccurs stays in the reference to the element declaration. This is the same syntax as that used in complex types to reference global element declarations. In fact, when a complex type references a named model group, it is as if the schema author cut and pasted the contents of the group element into the complex type definition. All local element declarations in the group become local to that complex type.

Example 15–2. Named model group with element references


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="description" type="xs:string"/>
  <xs:element name="comment" type="xs:string"/>

  <xs:group name="DescriptionGroup">
    <xs:sequence>
      <xs:element ref="description"/>
      <xs:element ref="comment" minOccurs="0"/>
    </xs:sequence>
  </xs:group>
</xs:schema>


Whether to use local element declarations in the group depends on whether you want these element declarations to be local to the complex type. For a complete discussion of global versus local element declarations, see Section 6.1.3 on p. 95.

15.2.2. Referencing named model groups

Named model groups may be referenced in complex types and in other groups. Since they are named global schema components, they may be referenced not only from within the same schema document, but also from other schema documents.

15.2.2.1. Group references

The syntax to reference a named model group is shown in Table 15–2. Named model groups are referenced through the ref attribute, just like other global schema components.

Table 15–2. XSD Syntax: named model group reference

Image
15.2.2.2. Referencing a named model group in a complex type

Example 15–3 shows the definition of the complex type PurchaseOrderType that references DescriptionGroup.

Example 15–3. Referencing a group from a complex type definition


<xs:complexType name="PurchaseOrderType">
  <xs:sequence>
    <xs:group ref="DescriptionGroup" minOccurs="0"/>
    <xs:element ref="items"/>
    <!--...-->
  </xs:sequence>
</xs:complexType>


Note that when referencing a group, minOccurs and maxOccurs may be specified to indicate how many times the contents of the group may appear. If minOccurs and maxOccurs are not specified, the default for both values is 1. The value for minOccurs must be less than or equal to the value for maxOccurs. This means that if a minOccurs value is specified that is more than 1, maxOccurs must also appear, with a value greater than or equal to minOccurs.

To illustrate how named model group references are handled, Example 15–4 shows a content model equivalent to Example 15–3 (assuming it was referencing DescriptionGroup from Example 15–1) but without a named model group being used. Note that the minOccurs="0" constraint that appeared in the group reference now appears in the sequence tag.

Example 15–4. Equivalent content model without a named model group reference


<xs:complexType name="PurchaseOrderType">
  <xs:sequence>
    <xs:sequence minOccurs="0">
      <xs:element name="description" type="xs:string"/>
      <xs:element name="comment" type="xs:string" minOccurs="0"/>
    </xs:sequence>
    <xs:element ref="items"/>
    <!--...-->
  </xs:sequence>
</xs:complexType>


In Example 15–3, the group is referenced within a sequence group. Named model groups may be referenced anywhere in the content model, and multiple named model group references (even to the same group) are allowed.

A named model group may also be referenced at the top level of a complexType, if the group contains the entire content model of the type. A complex type may only directly contain either one named model group (group) or one model group (all, sequence, or choice). Example 15–5 shows the definition of DescriptionType that references DescriptionGroup at the top level.

Example 15–5. Group reference at the top level of the content model


<xs:complexType name="DescriptionType">
  <xs:group ref="DescriptionGroup"/>
  <xs:attribute ref="xml:lang"/>
</xs:complexType>


15.2.2.3. Using all in named model groups

An all group may appear in named model groups, but the additional constraints on all groups still apply. Example 15–6 shows a legal use of an all group within a named model group. In version 1.0, an all group may only contain element declarations or references, not other groups.

Example 15–6. Group with an all model group


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:group name="DescriptionGroup">
    <xs:all>
      <xs:element name="description" type="xs:string"/>
      <xs:element name="comment" type="xs:string" minOccurs="0"/>
    </xs:all>
  </xs:group>
</xs:schema>


image

In version 1.0, since all groups can only appear at the top level of a complex type, the only way to reference a named model group that contains an all group is at the top level, as shown in Example 15–5. Version 1.1 has relaxed this constraint, and it is possible to reference a named model group that contains all from another all group, provided that minOccurs and maxOccurs are 1 on the group reference. However, it is still not legal to reference such a group from within a choice or sequence.

image
15.2.2.4. Named model groups referencing named model groups

Named model groups may reference other named model groups. This is shown in Example 15–7, where ProductPropertyGroup references DescriptionGroup.

Example 15–7. Group reference from a group


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:group name="ProductPropertyGroup">
    <xs:sequence>
      <xs:group ref="DescriptionGroup"/>
      <xs:element name="number" type="xs:integer"/>
      <xs:element name="name" type="xs:string"/>
    </xs:sequence>
  </xs:group>

  <xs:group name="DescriptionGroup">
    <xs:sequence>
      <xs:element name="description" type="xs:string"/>
      <xs:element name="comment" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:group>
</xs:schema>


The group references cannot be circular. That is, group a cannot reference itself, and group a cannot reference group b if the latter references group a, or another group c which references a, and so on. In addition, groups may only contain references to other groups; they cannot actually contain the definitions of groups, since all groups are defined globally.

15.3. Attribute groups

Attribute groups are used to represent groups of related attributes that appear in many different complex types. For example, if the attributes id, name, and version are used in multiple complex types in your schema, it may be useful to define an attribute group that contains declarations for these three attributes, and then reference the attribute group in various complex type definitions.

15.3.1. Defining attribute groups

Attribute groups are represented by attributeGroup elements, whose syntax is shown in Table 15–3. Attribute groups are required to have a name, and that name must be unique among all the attribute groups in the schema. Attribute groups are always defined globally, meaning that their parent is always schema.1

Table 15–3. XSD Syntax: attribute group definition

Image

Attribute groups may contain any number of attribute declarations and references to other attribute groups, plus one optional attribute wildcard. An attribute group cannot contain more than one attribute declaration with the same qualified name. In version 1.0, there is an additional constraint that an attribute group cannot contain more than one attribute declaration of type ID.

For example, if many complex type definitions will use the attributes id and version, you could define an attribute group that contains declarations for these two attributes, as shown in Example 15–8.

Example 15–8. Attribute group with local attribute declarations


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute name="id" type="xs:ID" use="required"/>
    <xs:attribute name="version" type="xs:decimal"/>
  </xs:attributeGroup>
</xs:schema>


In Example 15–8, the attributes are declared locally in the attribute group, as evidenced by the appearance of a name attribute instead of a ref attribute. It is also possible to use global attribute declarations and reference them from the attribute group, as shown in Example 15–9.

Example 15–9. Attribute group with attribute references


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:attribute name="id" type="xs:ID"/>
  <xs:attribute name="version" type="xs:decimal"/>

  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute ref="id" use="required"/>
    <xs:attribute ref="version"/>
  </xs:attributeGroup>
</xs:schema>


Note that the type attribute is now in the global attribute declaration, while the use attribute stays in the reference to the attribute declaration. This is the same way that complex types reference global attribute declarations. In fact, when a complex type references an attribute group, it is as if the schema author cut and pasted the contents of the attribute group definition into the complex type definition. All attributes that are declared locally in the attribute group become local to that complex type.

Whether to declare attributes locally in the attribute group depends on whether you want the attributes to be local to the complex type. For a complete discussion of global versus local attribute declarations, see Section 7.2.3 on p. 119.

Attribute groups may reference other attribute groups, as described in the next section. Attribute groups may also contain one attribute wildcard at the very end, as shown in Example 15–10. Attribute groups are limited to one attribute wildcard because a complex type cannot contain more than one attribute wildcard. See Section 12.7.3 on p. 298 for more information.

Example 15–10. Attribute group with a wildcard


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute name="id" type="xs:ID" use="required"/>
    <xs:attribute name="version" type="xs:decimal"/>
    <xs:anyAttribute namespace="##other"/>
  </xs:attributeGroup>
</xs:schema>


15.3.2. Referencing attribute groups

Attribute groups may be referenced in complex types and in other attribute groups. Since they are named global schema components, they may be referenced not only from within the same schema document, but also from other schema documents.

15.3.2.1. Attribute group references

The syntax to reference an attribute group is shown in Table 15–4. Attribute groups are referenced using the ref attribute, just like other global schema components.

Table 15–4. XSD Syntax: attribute group reference

Image
15.3.2.2. Referencing attribute groups in complex types

Example 15–11 shows the definition of the complex type ProductType that references the attribute group IdentifierGroup.

Example 15–11. Referencing an attribute group from a complex type definition


<xs:complexType name="ProductType">
  <xs:sequence>
    <!--...-->
  </xs:sequence>
  <xs:attributeGroup ref="IdentifierGroup"/>
  <xs:attribute name="effDate" type="xs:date"/>
</xs:complexType>


As shown in the example, references to attribute groups must appear after the content model (a sequence group in this example). They may appear before, after, or in between attribute declarations. The order of attribute groups (and attributes) in a complex type is insignificant.

To illustrate how XML Schema handles attribute group references, Example 15–12 shows a complex type definition that is equivalent to Example 15–11 (assuming it was referencing IdentifierGroup from Example 15–8) but without an attribute group being used. It is as if the schema author cut and pasted the attribute declarations from the attribute group.

Example 15–12. Equivalent complex type without an attribute group


<xs:complexType name="ProductType">
  <!--...-->
  <xs:attribute name="id" type="xs:ID" use="required"/>
  <xs:attribute name="version" type="xs:decimal"/>
  <xs:attribute name="effDate" type="xs:date"/>
</xs:complexType>


15.3.2.3. Duplicate attribute names

It is illegal to declare two attributes with the same qualified name in the same complex type. When using attribute groups, be sure that the referenced attribute group does not declare an attribute that is already declared directly in your complex type definition. Also, when referencing more than one attribute group in a complex type definition, be sure that the two attribute groups do not contain attribute declarations with identical names.

In Example 15–13, each of the attribute groups IdentifierGroup and VersionGroup contain a declaration of version, and the definition of ProductType references both attribute groups. This results in an illegal duplication of the version attribute for ProductType.

Example 15–13. Illegal duplication of attributes


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute name="id" type="xs:ID" use="required"/>
    <xs:attribute name="version" type="xs:decimal"/>
  </xs:attributeGroup>
  <xs:attributeGroup name="VersionGroup">
    <xs:attribute name="version" type="xs:decimal"/>
  </xs:attributeGroup>

  <xs:complexType name="ProductType">
    <xs:attributeGroup ref="IdentifierGroup"/>
    <xs:attributeGroup ref="VersionGroup"/>
  </xs:complexType>
</xs:schema>


15.3.2.4. Duplicate attribute wildcard handling

Each attribute group definition may only contain one attribute wildcard. However, it is possible for a complex type definition to reference two attribute groups, each of which contains an attribute wildcard. The complex type definition may also have a “local” wildcard, that is, an anyAttribute child.

In such a case, an effective attribute wildcard is determined by taking the intersection of the constraints of all of the wildcards, including the local wildcard and any that were included from attribute groups. A simple rule of thumb is that any replacement attribute must conform to all of the attribute wildcards for that complex type.

The value of processContents for this effective wildcard is the value of processContents for the local wildcard, if it is present. If it is not, the schema processor takes the value of processContents from the first attribute wildcard among the attributeGroup children.

For more information on attribute wildcards, see Section 12.7.3 on p. 298.

15.3.2.5. Attribute groups referencing attribute groups

Definitions of attribute groups may also reference other attribute groups. This is shown in Example 15–14, where HeaderGroup references IdentifierGroup. Attribute groups may only contain references to other attribute groups; they cannot actually contain the definitions of attribute groups, since all attribute groups are defined globally.

Example 15–14. Attribute group referencing an attribute group


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:attributeGroup name="HeaderGroup">
    <xs:attributeGroup ref="IdentifierGroup"/>
    <xs:attribute ref="xml:lang"/>
  </xs:attributeGroup>

  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute name="id" type="xs:ID" use="required"/>
    <xs:attribute name="version" type="xs:decimal"/>
  </xs:attributeGroup>

</xs:schema>


image

In version 1.0, attribute group references cannot be circular. That is, HeaderGroup cannot reference IdentifierGroup if IdentifierGroup also has a reference back to HeaderGroup (either directly or through a chain of attribute group references). In version 1.1, circular references are permitted, and the effect is that all of the attributes of both HeaderGroup and IdentifierGroup are included.

image
image

15.3.3. The default attribute group

In version 1.1, you can indicate that an attribute group is the default attribute group by specifying its name in the defaultAttributes attribute on the schema element. If such a default attribute group is defined, the attributes declared in that group will automatically be allowed for every complex type in the schema document, unless you specifically disallow it.

Example 15–15 shows a schema that defines a default attribute group. The defaultAttributes attribute on the schema names prod:IdentifierGroup as the default attribute group. It uses the prod prefix because the namespace must be taken into account when referencing any other schema component.

Example 15–15. Default attribute group


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:prod="http://datypic.com/prod"
           targetNamespace="http://datypic.com/prod"
           defaultAttributes="prod:IdentifierGroup">

  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute name="id" type="xs:ID" use="required"/>
    <xs:attribute name="version" type="xs:decimal"/>
  </xs:attributeGroup>

  <xs:complexType name="ProductType">
    <xs:sequence>
      <!--...-->
    </xs:sequence>
    <xs:attribute name="dept" type="xs:string"/>
  </xs:complexType>

  <xs:complexType name="CatalogType" defaultAttributesApply="false">
    <xs:sequence>
      <!--...-->
    </xs:sequence>
    <xs:attribute name="catalogNumber" type="xs:integer"/>
  </xs:complexType>
</xs:schema>


The effect of declaring the default attribute group is as if ProductType had included a reference to the attribute group; id and version attributes can appear on instances of this type. ProductType can also contain other attribute declarations or attribute group references. CatalogType, however, does not use the default attribute group, because it specifically disallows it using the attribute defaultAttributesApply="false".

image

15.4. Named groups and namespaces

Like most global components, named groups take on the target namespace of the schema document, so they need to be referenced with their qualified names. Example 15–16 works because the target namespace is the same as the default namespace, so that when the groups are referenced using the ref attribute, it is looking for their names in the target namespace.

Example 15–16. Named groups with a target namespace


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified"
           xmlns="http://datypic.com/prod"
           targetNamespace="http://datypic.com/prod">
  <xs:group name="DescriptionGroup">
    <xs:sequence>
      <xs:element name="description" type="xs:string"/>
      <xs:element name="comment" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:group>
  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute name="id" type="xs:ID" use="required"/>
    <xs:attribute name="version" type="xs:decimal"/>
    <xs:anyAttribute namespace="##other"/>
  </xs:attributeGroup>
  <xs:complexType name="PurchaseOrderType">
    <xs:sequence>
      <xs:group ref="DescriptionGroup" minOccurs="0"/>
      <xs:element ref="items"/>
      <!--...-->
    </xs:sequence>
    <xs:attributeGroup ref="IdentifierGroup"/>
  </xs:complexType>
</xs:schema>


When referencing named groups that are defined in a different namespace, the names need to be appropriately prefixed. This is shown in Example 15–17 where the values of the ref attribute use prefixed names prod:DescriptionGroup and prod:IdentifierGroup because that namespace is not the default in ord.xsd.

Example 15–17. Named groups across namespaces


ord.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified"
           xmlns="http://datypic.com/ord"
           xmlns:prod="http://datypic.com/prod"
           targetNamespace="http://datypic.com/ord">
  <xs:import namespace="http://datypic.com/prod"
             schemaLocation="prod.xsd"/>
  <xs:complexType name="PurchaseOrderType">
    <xs:sequence>
      <xs:group ref="prod:DescriptionGroup" minOccurs="0"/>
      <xs:element ref="items"/>
      <!--...-->
    </xs:sequence>
    <xs:attributeGroup ref="prod:IdentifierGroup"/>
  </xs:complexType>
</xs:schema>

prod.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified"
           xmlns="http://datypic.com/prod"
           targetNamespace="http://datypic.com/prod">
  <xs:group name="DescriptionGroup">
    <xs:sequence>
      <xs:element name="description" type="xs:string"/>
      <xs:element name="comment" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:group>
  <xs:attributeGroup name="IdentifierGroup">
    <xs:attribute name="id" type="xs:ID" use="required"/>
    <xs:attribute name="version" type="xs:decimal"/>
    <xs:anyAttribute namespace="##other"/>
  </xs:attributeGroup>
</xs:schema>


The locally declared elements have qualified names, that is, they are in a namespace and elementFormDefault is set to qualified. Note that the names of those elements declared in prod.xsd will retain the target namespace of that schema document, http://datypic.com/prod. Being referenced as a group from a schema document with a different target namespace does not change their namespace, even though they are locally declared.

15.5. Design hint: Named groups or complex type derivations?

There may be cases where it is unclear when to define a named group and when to use complex type derivation. Complex type derivation, like named groups, serves the purpose of allowing reuse of content models and attributes.

For example, if there are several places in your purchase order where you allow a description optionally followed by a comment, you could define a named model group to represent this. You could then reuse this group in the content model of several, possibly dissimilar complex types.

However, it is also possible to represent this differently. You can define a base complex type that has the descriptive element declarations, and several complex types that extend the base type to specify additional children. Example 15–18 illustrates this approach.

The same dilemma can apply to attributes, which can be reused both through attribute groups and through complex type extensions.

Either of these two methods is legal, but each has its advantages and disadvantages. Use a named model group if:

• The fragment you want to reuse does not appear first in some of the types’ content models. This is because extension adds a derived type’s content model after its base type’s content model as if they were in a sequence group. In the above example, if the descriptive information did not come first, it would have been impossible to use extension.

Example 15–18. Reusing content model fragments through derivation


<xs:complexType name="DescribedType">
  <xs:sequence>
    <xs:element name="description" type="xs:string"/>
    <xs:element name="comment" type="xs:string" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="PurchaseOrderType">
  <xs:complexContent>
    <xs:extension base="DescribedType">
      <xs:sequence>
        <xs:element ref="items"/>
        <!--...-->
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

<xs:complexType name="ItemsType">
  <xs:complexContent>
    <xs:extension base="DescribedType">
      <xs:sequence>
        <xs:element ref="product" maxOccurs="unbounded"/>
        <!--...-->
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>


• The types are dissimilar concepts that just happen to share a small content model fragment. It may not be intuitive to derive them from the same base type.

On the other hand, use a complex type derivation if:

• The reusable content model fragments appear at the beginning of the content model.

• The types have mostly the same content model with just a few differing element or attribute declarations.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.170.174