- From: Jeni Tennison <jeni@jenitennison.com>
- Date: Mon, 25 Feb 2002 18:25:57 +0000
- To: Brenda Bell <bbell@juicesoftware.com>
- CC: "'xmlschema-dev@w3.org'" <xmlschema-dev@w3.org>
Hi Brenda, > I'm trying to develop a schema that requires element X to: > > have exactly one each of child elements A, B and C in any order > allow other child elements from any other namespace > > I've been able to develop schemas that meet two of my three > requirements but not all three. I've also been able to develop a > schema that appears to meet all three, however validation succeeds > when any of the required elements are omitted. If anyone else has > done something similar, I would really appreciate any guidance you > have to offer. Yes, if you use xs:all to allow the elements to occur in any order then you can't use the xs:any wildcard to allow any combination of elements. If you use substitution groups, you can allow A, B or C in any order, and use a wildcard, but you can't guarantee that there's only one each of A, B and C. So you have three options, I think: Firstly, you could make the XML Schema enumerate the possible combinations. This is a bit of a headache - not *too* awful with three elements, but pretty bad: <xs:sequence> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> <xs:choice> <xs:sequence> <xs:element ref="A" /> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> <xs:choice> <xs:sequence> <xs:element ref="B" /> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> <xs:element ref="C" /> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> <xs:sequence> <xs:element ref="C" /> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> <xs:element ref="B" /> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:choice> </xs:sequence> ... </xs:choice> Secondly, you could use a more general content model, and then add any additional constraints using a schema adjunct, such as Schematron. For example: <xs:choice minOccurs="3" maxOccurs="unbounded"> <xs:annotation> <xs:appinfo> <sch:rule context="X"> <sch:assert test="count(A) = 1"> There can only be one A element </sch:assert> <sch:assert test="count(B) = 1"> There can only be one B element </sch:assert> <sch:assert test="count(C) = 1"> There can only be one C element </sch:assert> </sch:rule> </xs:appinfo> </xs:annotation> <xs:element ref="A" /> <xs:element ref="B" /> <xs:element ref="C" /> <xs:any namespace="##other" /> </xs:choice> Thirdly, you could make your markup language easier to represent with an XML Schema by wrapping the elements in other namespaces within another element. Then you can use xs:all as follows: <xs:all> <xs:element ref="A" /> <xs:element ref="B" /> <xs:element ref="C" /> <xs:element name="D"> <xs:complexType> <xs:sequence> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> </xs:element> </xs:all> Finally, you could make your markup language easier to represent with an XML Schema by choosing a canonical representation in which the order of A, B and C (and the wildcard) is specified. You could constrain such a content model very easily: <xs:sequence> <xs:element ref="A" /> <xs:element ref="B" /> <xs:element ref="C" /> <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> You could provide a small script, stylesheet or query to transform from unordered versions to the canonical ordering for the purpose of validation. Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/
Received on Monday, 25 February 2002 13:26:05 UTC