Reputation: 106569
I have a document type similar to the following:
<foo>
<settings>
<!-- Must be present; in any order -->
<time>abc</time>
<validRun>true</validRun>
<!-- Tool may add whatever ones it wants -->
<somethingNotCheckedFor>abc</somethingNotCheckedFor>
</settings>
</foo>
The following document is semantically the same as the preceding document:
<foo>
<settings>
<validRun>true</validRun>
<somethingNotCheckedFor>abc</somethingNotCheckedFor>
<time>abc</time>
</settings>
</foo>
but the following is invalid:
<foo>
<settings>
<validRun>true</validRun>
<somethingNotCheckedFor>abc</somethingNotCheckedFor>
<!-- Error: Required element "time" not present -->
</settings>
</foo>
I tried something like the following but this does not work because <xs:all>
is not allowed to contain <xs:any>
:
<xs:all>
<xs:element name="time" />
<xs:element name="validRun" />
<xs:any />
</xs:all>
Is there some means to do this in W3C Schema?
Upvotes: 4
Views: 1307
Reputation: 25034
You can use XSD 1.1, which does allow wildcards to appear within all-groups.
If your required elements are in a namespace and you can require that elements added by the generator not be in that namespace, then you can write a content model using choices and sequences that recognizes the language you want (if you really have only two required elements, it's not too hard; if you have three or four it becomes cumbersome, and if you have more than five you don't want to do this way without a compiler). What you need is a content model like this:
<xs:sequence>
<xs:any namespace="##other"
minOccurs="0"
maxOccurs="unbounded"/>
<xs:choice>
<xs:sequence>
<xs:element ref="time"/>
<xs:any namespace="##other"
minOccurs="0"
maxOccurs="unbounded"/>
<xs:element ref="validRun"/>
</xs:sequence>
<xs:sequence>
<xs:element ref="validRun"/>
<xs:any namespace="##other"
minOccurs="0"
maxOccurs="unbounded"/>
<xs:element ref="time"/>
</xs:sequence>
</xs:choice>
<xs:any namespace="##other"
minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
You can declare settings
with a content model containing just a lax repeating wildcard, and check at the application level (1) that it contains both time
and validRun
and (2) that those two children are valid.
Of these, I think XSD 1.1 is likely to produce the most satisfactory results, if you can use an XSD 1.1 validator. At the moment, both Xerces J and Saxon-EE support XSD 1.1; most other XSD tools do not.
Upvotes: 3
Reputation: 12154
I guess you know how to use <any/>
element!! ie, you cannot take <any/>
element by literal meaning but you have to declare possible list of elements ..
I guess this will explain the usage of <any/>
as well as solution to your problem!! :))
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="foo" type="foo"/>
<xs:complexType name="foo">
<xs:sequence>
<xs:element name="settings" type="settings"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="settings">
<xs:sequence>
<xs:any minOccurs="1" maxOccurs="1"/>
<xs:any minOccurs="1" maxOccurs="1"/>
<xs:any minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="somethingNotCheckedFor" type="xs:string"/>
<xs:element name="time" type="xs:string" />
<xs:element name="validRun" type="xs:boolean" />
<xs:element name="somethingNotCheckedForTWO" type="xs:string"/>
</xs:schema>
The above schema doesn't allow any other elements than declared ones .. And it doesn't allow them to be repeated also no restriction on order!!
You can declare all possible elements in place of <somethingNotCheckedFor/>
!! like I have declared <somethingNotCheckedForTWO/>
as well.
Below listed XML samples are succeed with validation! :
1.
<?xml version="1.0" encoding="utf-8"?>
<foo>
<settings>
<time>abc</time>
<somethingNotCheckedForTWO>abc</somethingNotCheckedForTWO>
<validRun>true</validRun>
</settings>
</foo>
2.
<?xml version="1.0" encoding="utf-8"?>
<foo>
<settings>
<time>abc</time>
<validRun>true</validRun>
<somethingNotCheckedForTWO>abc</somethingNotCheckedForTWO>
</settings>
</foo>
3.
<?xml version="1.0" encoding="utf-8"?>
<foo>
<settings>
<somethingNotCheckedFor>abc</somethingNotCheckedFor>
<time>abc</time>
<validRun>true</validRun>
</settings>
</foo>
Upvotes: 2