I'm trying to validate some existing XML files in my project. An example structure looks like:
<resources>
<file name="one" path="C:\test\one.txt" />
<cache path="C:\test\cache\" />
<file name="two" path="C:\test\two.txt" />
<bundle name="myFolder">
<file name="three" path="C:\test\three.txt" />
<file name="four" path="C:\test\four.txt" />
</bundle>
<file name="one" path="C:\test\one.txt" />
<bundle name="myFolder">
<file name="three" path="C:\test\three.txt" />
<file name="four" path="C:\test\four.txt" />
</bundle>
<file name="one" path="C:\test\one.txt" />
</resources>
In words, what I want is a structure with root element resources
, which has children
- At most one
cache
element, in any order - Any number of
file
andbundle
elements, in any order bundle
contains any number offile
elements
This is my current XSD (drawing from this answer):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:complexType name="cache">
<xs:attribute name="path" type="xs:string" />
</xs:complexType>
<xs:complexType name="file">
<xs:attribute name="name" type="xs:string" />
<xs:attribute name="path" type="xs:string" />
</xs:complexType>
<xs:complexType name="bundle">
<xs:choice maxOccurs="unbounded">
<xs:element name="file" type="file" maxOccurs="unbounded" />
</xs:choice>
<xs:attribute name="type" />
<xs:attribute name="name" />
</xs:complexType>
<xs:group name="unboundednoncache">
<xs:choice>
<xs:element name="file" type="file" />
<xs:element name="bundle" type="bundle" />
</xs:choice>
</xs:group>
<xs:element name="resources">
<xs:complexType>
<xs:sequence>
<!-- Validates if this next line is removed,
and the cache element is moved to first -->
<xs:group ref="unboundednoncache" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="cache" type="cache" minOccurs="0" maxOccurs="1" />
<xs:group ref="unboundednoncache" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
This gives me the error:
Cos-nonambig: File And File (or Elements From Their Substitution Group) Violate "Unique Particle Attribution". During Validation Against This Schema, Ambiguity Would Be Created For Those Two Particles.
I can get the first XSD to validate if I remove the first <xs:group>
in the XSD and move the cache
element to be the first child in the XML, but I want the cache element to be valid anywhere.
(Prior to this version I was using:
<xs:choice maxOccurs="unbounded">
<xs:element name="cache" type="cache" minOccurs="0" maxOccurs="1" />
<xs:element name="file" type="file" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="bundle" type="bundle" minOccurs="0" maxOccurs="unbounded" />
</xs:choice>
.. but that allows multiple cache elements, which I don't want either.)
Why does my XSD violate "unique particle attribution", and how can I fix it?