This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 6545 - Using Assertions to restrict complex types
Summary: Using Assertions to restrict complex types
Status: CLOSED LATER
Alias: None
Product: XML Schema
Classification: Unclassified
Component: Structures: XSD Part 1 (show other bugs)
Version: 1.1 only
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: David Ezell
QA Contact: XML Schema comments list
URL:
Whiteboard:
Keywords: resolved
Depends on:
Blocks:
 
Reported: 2009-02-09 10:11 UTC by Michael Kay
Modified: 2012-06-18 22:49 UTC (History)
2 users (show)

See Also:


Attachments

Description Michael Kay 2009-02-09 10:11:59 UTC
I've been writing a conference paper about XSD 1.1, and specifically about assertions, and I hit a rather embarrassing usability problem. Sorry for raising it at this stage of the game, but it's exactly at this stage that usability problems tend to be discovered.

I was trying to show how useful assertions are in customizing a schema for local use. For example, suppose there is a standard IPO schema for internal purchase orders, and you want to customize it so that money amounts are always in dollars. So one should be able to say:

<xs:element name="our-IPO">
  <xs:complexType name="our-IPO-type">
    <xs:complexContent>
      <xs:restriction base="IPO-type">
        <xs:assert test="every $c in .//@currency satisfies $c='USD'"/>
      </xs:restriction>
    </xs:complexContent>
  <xs:complexType>
</xs:element>

Simple, isn't it? But wrong. Applying xs:restriction to a complex type inherits the attribute uses of the base type, but not the particle or the attribute wildcard. If you want your restricted type to have the same content model as the base type, you have to copy it across, in all its gory detail. And of course every time it changes, your new type has to change too.

I've got a few ideas on how to fix this. I'll start with the one that I think is best but most radical, which I'll call the Grand Plan.

The Grand Plan is to remove the assymmetry in complex type restriction as to which parts of the base type definition are inherited and which are explicitly redefined. (This is all at the XML representation level, the component level is unaffected.)

To xs:restriction (for complex types) we add an attribute @inherit, whose value is a list of tokens from the set (content, attributes, anyAttribute) or the value #all to indicate all of the above. The default value, for compatibility reasons, is "attributes". The @inherit attribute indicates which aspects of the base type definition are inherited. If attributes are inherited, we allow attributes to be redefined in the restricted type as at present, but if content or anyAttribute is inherited, we require the restricted type to specify no content or no attribute wildcard respectively.

Add the XML representation rule that if xs:restriction/@inherit includes content, then the xs:restriction element must not have a sequence, choice, all or group child; and if it includes anyAttribute, then it must not have an anyAttribute child.

The mapping rule for attribute uses (3.4.2.4) is changed as follows: in 3.2, change "If T is a complex type definition and {derivation method} = restriction" to add " and the [inherit] attribute of the <restriction> element includes 'attributes'"

The mapping rule for atribute wildcards (3.4.2.5) is changed as follows: rule 2.1, currently "If  {derivation method} = restriction  , then the ·complete wildcard·;" becomes: 2.1 If {derivation method} = restriction, then the relevant case among the following: 2.1.1 if the [inherit] attribute of the <restriction> element includes 'anyAttribute' then the base wildCard 2.1.2 otherwise, the ·complete wildcard·. And promote the definition of "base WildCard" from 2.2.1.

The mapping rule for complex content {content type} (3.4.2.3.3) is changed as follows: in 4.1 ("4.1 If  {derivation method} = restriction") add the rule "If the inherit attribute of the <restriction> element includes "content", then {base type definition}.{content type}

That's the Grand Plan. If it's too much to stomach, can we get away with less?

Plan B: We could cut it down so the only new option is inherit="content".

Plan C: We could cut it down further so there is no new syntax, but inherit="content" is implicit in the case of an xs:restriction that has an xs:assert child but no xs:sequence|xs:choice|xs:all|xs:group child. Yuk.

Plan G: A different approach. We could introduce "manual inheritance" for complex types by syntax such as:

<xs:element name="our-IPO">
  <xs:complexType name="our-IPO-type">
    <xs:complexContent>
      <xs:restriction base="IPO-type">
        <xs:group/>
        <xs:assert test="every $c in .//@currency satisfies $c='USD'"/>
      </xs:restriction>
    </xs:complexContent>
  <xs:complexType>
</xs:element>

where the absence of a "ref" attribute on xs:group means "an anonymous model group corresponding to the content model of the base type". This is perhaps the least disruptive proposal.

Plan H: Introduce special syntax for the case where a complex type is restricted only by addition of assertions:

<xs:element name="our-IPO">
  <xs:complexType name="our-IPO-type">
     <xs:restriction base="IPO-type">
        <xs:assert test="every $c in .//@currency satisfies $c='USD'"/>
     </xs:restriction>
  <xs:complexType>
</xs:element>
Comment 1 Henry S. Thompson 2009-02-10 13:49:43 UTC
I think a version of Plan G makes a lot of sense, and Plan G is the only one I see that we could add w/o going back to Last Call yet again.  My preferred version would be to say that

 a) By default, a named model group is defined in conjunction with every
    non-empty CTD;

 b) The name of that group is xsd_dgd_[the name of the CTD] in the target
    namespace of the CTD;

 c) <xs:group/> is allowed if you are eventually inside an <xs:restriction>...
    with the result having as it were ref=xsd_dgd_ ancestor::xs:restriction/@base

Otherwise we couldn't go through the named-group reference route, which is much simpler than actually chasing around in component space.  I realise this raises the in-principle possibility of name conflict.  We could fix that by including a non NCName character such as space or initial #, but that would lose the real added value of allowing other, explicit, reference to these CTD-content-based named groups.

What about inheritance of assertions themselves?
Comment 2 Michael Kay 2009-02-10 17:08:45 UTC
I think I prefer the solution of an empty <xs:group/> element to one with an artificial invented name, though I wouldn't object to something like <xs:group ref="#baseModel"/>

I think that the current rules cause assertions to be inherited - no problems there.
Comment 3 David Ezell 2009-02-20 17:35:36 UTC
The WG has some sympathy for option 'G' as a simple way forward.  However, such a change seems to call for another LCWD.  The WG is deferring a decision on how to resolve this bug until closer to transition to CR.
Comment 4 Sandy Gao 2009-04-20 21:36:41 UTC
During its 2009-04-17 telecon, the schema WG decided to resolve this issue without any change to schema 1.1.

Michael, if you would indicate your concurrence with or dissent from the WG's disposition of the comment by closing or reopening the issue, we'll be grateful. If we don't hear from you in the next two weeks, we'll assume that silence implies consent.
Comment 5 Michael Kay 2012-06-18 22:49:33 UTC
Noted that there is a workaround to this problem: define the derived type not as a restriction, but as a vacuous extension:

<xs:element name="our-IPO">
  <xs:complexType name="our-IPO-type">
    <xs:complexContent>
      <xs:extension base="IPO-type">
        <xs:assert test="every $c in .//@currency satisfies $c='USD'"/>
      </xs:extension>
    </xs:complexContent>
  <xs:complexType>
</xs:element>

Counter-intuitive, but it seems to meet the requirement.