320 likes | 510 Views
Substitution Groups in XML Schemas. Tomer Shiran Winter 2003/4 Semester. What’s included?. Why substitution groups? Substitutions in an XML instance Declaring a substitution group The substitution group hierarchy Type constraints for substitution groups Controlling substitution groups
E N D
Substitution Groupsin XML Schemas Tomer Shiran Winter 2003/4 Semester
What’s included? • Why substitution groups? • Substitutions in an XML instance • Declaring a substitution group • The substitution group hierarchy • Type constraints for substitution groups • Controlling substitution groups • Alternatives to substitution groups
Why substitution groups?example1.xml <?xml version="1.0" encoding="UTF-8"?> <items> <product type="hat"> <number>111</number> <name>Ten-Gallon Hat</name> <size>27</size> </product> <product type="shirt"> <number>222</number> <name>Short-Sleeved Linen Blouse</name> <size>40</size> <color>Red</color> </product> … <product> <number>444</number> <name>Special Seasonal</name> </product> </items>
Why Substitution Groups? (Cont.) • The previous design has various problems: • We want to allow different content models for different kinds of products: • Shirts have a mandatory size and an optional color • Hats have a mandatory size • Umbrellas have a mandatory radius • We want to use descriptive element names that indicate the type of product (e.g., shirt and hat instead of product). • We want to accept new kinds of products without altering the original schema. • Substitution groups address these issues…
Whenever the head element is referenced in a content model, one of the member elements may be substituted in place of the head. Substitutions in an XML instanceexample2.xml <?xml version="1.0" encoding="UTF-8"?> <items xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:noNamespaceSchemaLocation="example2.xsd"> <hat> <number>111</number> <name>Ten-Gallon Hat</name> <size>27</size> </hat> <shirt> <number>222</number> <name>Short-Sleeved Linen Blouse</name> <size>40</size> <color>Red</color> </shirt> … <product> <number>444</number> <name>Special Seasonal</name> </product> </items>
Declaring a substitution groupexample2.xsd <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="items" type="ItemsType"> <xs:key name="productNumberKey"> <xs:selector xpath="./*"/> <xs:field xpath="number"/> </xs:key> </xs:element> <xs:complexType name="ItemsType"> <xs:sequence> <xs:element ref="product" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:element name="product" type="ProductType"/> <xs:complexType name="ProductType"> <xs:sequence> <xs:element name="number" type="xs:integer"/> <xs:element name="name" type="xs:string"/> </xs:sequence> </xs:complexType> Anyglobal element can be the head of a substitution group.
Declaring a substitution group (Cont.)example2.xsd (Cont.) <xs:element name="shirt" type="ShirtType"substitutionGroup="product"/> <xs:complexType name="ShirtType"> <xs:complexContent> <xs:extension base="ProductType"> <xs:sequence> <xs:element name="size" type="xs:integer"/> <xs:element name="color" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="hat" type="HatType"substitutionGroup="product"/> <xs:complexType name="HatType"> <xs:complexContent> <xs:extension base="ProductType"> <xs:sequence> <xs:element name="size" type="xs:integer"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType>
Declaring a substitution group (Cont.)example2.xsd (Cont.) <xs:element name="umbrella" type="UmbrellaType"substitutionGroup="product"/> <xs:complexType name="UmbrellaType"> <xs:complexContent> <xs:extension base="ProductType"> <xs:sequence> <xs:element name="radius" type="xs:integer"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:schema>
The substitution group hierarchy • Each substitution group has one head element and one or more members. • If the head element is in a different namespace (i.e., the schema document in which it is declared has a target namespace), a prefix must be used in the substitutionGroup attribute (e.g., ord:product). • Each element declaration can only be a direct member of one substitution group – membership is transitive, but not symmetric. • An element declaration can be a member of a substitution group and the head of a different substitution group.
The substitution group hierarchy (Cont.) • hat, shirt, blouse, tShirt, and umbrella can substitute for product. • blouse and tShirt can substitute for shirt. <xs:element name="product" type="ProductType"/> <xs:element name="hat" type="HatType" substitutionGroup="product"/> <xs:element name="shirt" type="ShirtType" substitutionGroup="product"/> <xs:element name="blouse" type="BlouseType" substitutionGroup="shirt"/> <xs:element name="tShirt" type="TShirtType" substitutionGroup="shirt"/> <xs:element name="umbrella" type="UmbrellaType" substitutionGroup="product"/>
Type constraints for substitution groups • Members of a substitution group must havetypes that are: • The same as the type of the head, or • Derived from the head by either extension or restriction (directly or indirectly, through multiple levels of restriction or extension) • XMLSPY 2004 doesn’t enforce this rule. • If an element declaration doesn’t specify a type attribute or a simpleType or complexType child, the type definition of the declaration is the same type as the element specified by the substitutionGroup attribute (the head of the group).
Controlling substitution groups • The final attribute limits the declaration of substitution groups in schemas. • The block attribute limits the use of substituted elements in instances. • The abstract attribute forces element substitution in instances.
The final attributePreventing substitution group declarations <xs:element name="product" type="ProductType"final="#all"/> <xs:element name="product" type="ProductType"final="extension"/> <xs:element name="product" type="ProductType"final="restriction"/> <xs:element name="product" type="ProductType"final=""/>
The block attributeBlocking substitution in instances <xs:element name="product" type="ProductType"block="substitution"/> • With this declaration of product, the schema in example2.xsd would have been legal, but the instance in example2.xml would have been illegal.
final vs. block • Terminology: • final specifies “substitution group exclusions”, which is a static constraint – it affects the element derivation hierarchy • block specifies “disallowed substitutions”, which is a runtime constraint – it affects the instance structure • substitutionGroup specifies “substitution group affiliation” • There are 32 different ways to set the constraints: • 22 for final (extension and restriction) • 23 for block (substitution, extension, and restriction)
final vs. block (Cont.)An example • A type hierarchy: • Element declarations: • <xs:element name="top" type="TopType"/> • <xs:element name="middle" type="MiddleType" block="substitution" substitutionGroup="top"/> • <xs:element name="bottom" type="BottomType" substitutionGroup="middle"/> • What substitutions can be made in the instance? • middle instead of top? • bottom instead of middle? • bottom instead of top? This is valid because there is no static constraint in middle. Yes No Yes
The abstract attributeForcing substitution <xs:element name="product" type="ProductType"abstract="true"/> • An abstract element declaration can never apply to an instance element. • It can serve as the head of a substitution group (like an abstract class in Java/C#). • In XMLSPY 2004 (but not in the standard or in other implementations), members of a substitution group with an abstract head must explicitly specify a type. … <umbrella> … </umbrella> <product> <number>444</number> <name>Special Seasonal</name> </product> </items>
Specifies that local elements (e.g., number) also belong to the target namespace (avoids prefixes in the instance). The abstract attribute(Cont.) example3.xsd <?xml version="1.0" encoding="UTF-8"?> <xs:schema targetNamespace="http://example.org/ord" xmlns:ord="http://example.org/ord" xmlns="http://example.org/ord" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="items" type="ItemsType"> <xs:key name="productNumberKey"> <xs:selector xpath="./*"/> <xs:field xpath="ord:number"/> </xs:key> </xs:element> <xs:complexType name="ItemsType"> <xs:choice maxOccurs="unbounded"> <xs:element ref="shirt"/> <xs:element ref="hat"/> <xs:element ref="umbrella"/> <xs:element ref="otherProduct"/> </xs:choice> </xs:complexType>
The abstract attribute(Cont.) example3.xsd (Cont.) <xs:element name="otherProduct" type="ProductType" abstract="true"/> <xs:complexType name="ProductType"> <xs:sequence> <xs:element name="number" type="xs:integer"/> <xs:element name="name" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:element name="shirt" type="ShirtType"/> <xs:complexType name="ShirtType"> <xs:complexContent> <xs:extension base="ProductType"> <xs:sequence> <xs:element name="size" type="xs:integer"/> <xs:element name="color" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> … </xs:schema>
The abstract attribute(Cont.) example3ext.xsd <?xml version="1.0" encoding="UTF-8"?> <xs:schema targetNamespace="http://example.org/ord" xmlns="http://example.org/ord" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:include schemaLocation="example3.xsd"/> <xs:element name="sweater" type="SweaterType"substitutionGroup="otherProduct"/> <xs:complexType name="SweaterType"> <xs:complexContent> <xs:extension base="ShirtType"> <xs:attribute name="material" default="cotton/polyester"> … </xs:attribute> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="suit"substitutionGroup="otherProduct"/> </xs:schema>
The abstract attribute(Cont.)example3.xml <?xml version="1.0" encoding="UTF-8"?> <items xmlns="http://example.org/ord" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://example.org/ord example3ext.xsd"> <hat> <number>111</number> <name>Ten-Gallon Hat</name> <size>27</size> </hat> … <sweater material="cotton"> <number>444</number> <name>Super Sweater</name> <size>38</size> <color>Blue</color> </sweater> <suit> <number>555</number> <name>Million-Dollar Suit</name> </suit> </items> Notice the whitespace! Won’t work in XMLSPY 2004 (because the suit element declaration doesn’t explicitly specify a type in the schema)!
Alternatives to substitution groups • Reusable choice groups • Substituting a derived type in the instance
Reusable choice groupsexample4.xsd <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="items" type="ItemsType"> ... </xs:element> <xs:complexType name="ItemsType"> <xs:group ref="ProductGroup" maxOccurs="unbounded"/> </xs:complexType> … <xs:group name="ProductGroup"> <xs:choice> <xs:element name="product" type="ProductType"/> <xs:element name="shirt" type="ShirtType"/> <xs:element name="hat" type="HatType"/> <xs:element name="umbrella" type="UmbrellaType"/> </xs:choice> </xs:group> </xs:schema>
Reusable choice groups (Cont.) Pros: • Easy to see the list of members of the “substitution group” Cons: • Cumbersome to add new element declarations to the “substitution group” (a redefinition is needed, and it can only be done in schema documents with the same target namespace)
Derived type substitution in the instance • Instead of declaring shirt, hat, and umbrella, we just declare their data types and specify all products as product elements. • The derived types are substituted in the instance by specifying the xsi:type attribute. • The block attribute of complexType or element can be specified in the schema in order to block substitution of derived types. • If the block attribute is used in an element declaration (an element element), and its value is "#all" or "substitution", then the element cannot be substituted in the instance.
Derived type substitution (Cont.)example5.xsd <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> … <xs:complexType name="ItemsType"> <xs:sequence> <xs:element name="product" type="ProductType“ maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="ProductType"> … </xs:complexType> <xs:complexType name="ShirtType"> <xs:complexContent> <xs:extension base="ProductType"> … </xs:extension> </xs:complexContent> </xs:complexType> … </xs:schema>
Derived type substitution (Cont.)example5.xml <?xml version="1.0" encoding="UTF-8"?> <items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="example5.xsd"> <productxsi:type="HatType"> <number>111</number> <name>Ten-Gallon Hat</name> <size>27</size> </product> <productxsi:type="ShirtType"> <number>222</number> <name>Short-Sleeved Linen Blouse</name> <size>40</size> <color>Red</color> </product> … <product> <number>444</number> <name>Special Seasonal</name> </product> </items> If ProductType was an abstract type, the xsi:type would be required.
Derived type substitution (Cont.) Pros: • Instance may be easier to process Cons: • Looks slightly more complicated, and requires a declaration of the XML Schema Instance Namespace • Difficult concept for those who unacquainted with schemas (they expect the tag name to identify the “type” of the element) • Impossible to write a DTD that would validate this instance to the same degree
Requirements for XML Schema 1.1 • Categories in the requirements document: • A requirement must be met in XML Schema 1.1. • A desideratum should be met in XML Schema 1.1. • An opportunistic desideratum may be met in XML Schema 1.1. • Requirements: • Improve interaction between exclusions and disallowed substitutions in the element component. • Address problems with the interaction between wildcards and substitution groups. Specifically, resolve the bug where if complex type A has a wildcard, and B restricts A, then it can restrict the wildcard to a set of elements that match the wildcard. Not all elements in the substitution groups of those elements necessarily match the wildcard – so B is not a subset of A. • Desiderata: • Allow an element declaration to be in more than one substitution group.
SummarySubstitution groups – flexibility as a two-edged sword Pros: • Content models can accept additional elements from a variety of namespaces and schema documents (unlike reusable choice groups, which require redefine to extend) • No special syntax is needed in an instance (no xsi:type required)
Summary (Cont.)Substitution groups – flexibility as a two-edged sword Cons: • Hard to tell which elements are actually substitutable – especially when they belong to different schema documents and different namespaces • Instance may be hard to process (but block and final can help) • JAXB and .NET XML serialization don’t support schemas with substitution groups • Schema authors must be well acquainted with most of the features of XML schemas (namespaces, complex types, type derivation, etc.)
Any questions? Thank You!