I'm writing a Schema for our (old) XML output, and have run into an issue where an element may contain some sub-elements. I'm using an "xs:all minOccurs="0" in the schema, but when I validate against the XML, it's requiring at least one instance of each sub-element.
<xs:element name="Project">
<xs:complexType>
<xs:all minOccurs="0" maxOccurs="1">
<xs:element ref="lit:ProductPool" minOccurs="1"/>
<xs:element ref="lit:ProjectDefaults"/>
<xs:element ref="lit:TaskInfo"/>
</xs:all>
<xs:attribute name="Name" type="lit:TextType_2010"/>
... a bunch more
Then when I use that to validate some XML that only has the "ProductPool" sub element, the validator complains that the other 2 are missing and are required.
Reason: The following elements are expected after this location (see below)
'lit:TaskInfo'
'lit:ProjectDefaults'
Error location: MetrixXML / Project
Details
cvc-complex-type.1.4: The content for element <Project> is incomplete.
cvc-type.3.2: Element <Project> is not valid with respect to type definition '{anonymous}'.
cvc-elt.5.2.1: The element <Project> is not valid with respect to the actual type definition '{anonymous}'.```
That is because your MinOccurs is on the All node rather than on the ProjectDefaults or TaskInfo, by default they will be minOccurs once. So if ProductPool was not there, it will not complain, but as soon as you have ProductPool, it will expect the other two.
Resolve it by setting MinOccurs = 0 on ProjectDefaults and TaskInfo
On an <xs:element>*, the value of attributes minOccurs and maxOccurs both default to 1.
On an <xs:all>*, the value of attributes minOccurs and maxOccurs both default to 1.
* Click link to see specification
That means the follow 3 constructs are the same:
<!-- As defined in question -->
<xs:all minOccurs="0" maxOccurs="1">
<xs:element ref="lit:ProductPool" minOccurs="1"/>
<xs:element ref="lit:ProjectDefaults"/>
<xs:element ref="lit:TaskInfo"/>
</xs:all>
<!-- Without specifying values that are same as defaults -->
<xs:all minOccurs="0">
<xs:element ref="lit:ProductPool"/>
<xs:element ref="lit:ProjectDefaults"/>
<xs:element ref="lit:TaskInfo"/>
</xs:all>
<!-- Specifying values, even if same as defaults -->
<xs:all minOccurs="0" maxOccurs="1">
<xs:element ref="lit:ProductPool" minOccurs="1" maxOccurs="1"/>
<xs:element ref="lit:ProjectDefaults" minOccurs="1" maxOccurs="1"/>
<xs:element ref="lit:TaskInfo" minOccurs="1" maxOccurs="1"/>
</xs:all>
This means that if the all is used in the actual XML, by having any of ProductPool, ProjectDefaults, or TaskInfo present, then all 3 must be present.
The minOccurs="0" means that you can have none of them, or all three of them.
Perhaps you believed that minOccurs defaulted to 0, in which case you should have written it like this:
<xs:all minOccurs="0">
<xs:element ref="lit:ProductPool"/>
<xs:element ref="lit:ProjectDefaults" minOccurs="0"/>
<xs:element ref="lit:TaskInfo" minOccurs="0"/>
</xs:all>
With such a definition, ProductPool is optional, and can appear by itself. ProjectDefaults and TaskInfo are also optional, but if either is present, then ProductPool is required. The three elements can appear in any order.
Related
It seems like it should be possible to restrict a substitution group to a single element in that group. Due to the handling of substitution groups and elements during validation, however, the intuition only applies to certain cardinalities.
For example, the following schema is not valid:
<xs:element name="representedOrganization" type="Organization"/>
<xs:element name="scopingOrganization" type="Organization" substitutionGroup="representedOrganization"/>
<xs:complexType name="Test.Parent">
<xs:sequence>
<xs:element ref="representedOrganization" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Test.Child">
<xs:complexContent>
<xs:restriction base="Test.Parent">
<xs:sequence>
<xs:element name="scopingOrganization" type="Organization" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
However, a small change to the cardinality (i.e. minOccurs) of the restriction is valid:
<xs:element name="representedOrganization" type="Organization"/>
<xs:element name="scopingOrganization" type="Organization" substitutionGroup="representedOrganization"/>
<xs:complexType name="Test.Parent">
<xs:sequence>
<xs:element ref="representedOrganization" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Test.Child">
<xs:complexContent>
<xs:restriction base="Test.Parent">
<xs:sequence>
<xs:element name="scopingOrganization" type="Organization" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
This does not behave intuitively... but why?
This is a vicious interaction between the handling in two locations.
Under Schema Component Constraint: Particle Valid (Restriction), the specification clarifies that:
2.1 Any top-level element declaration particle (in R or B) which is the {substitution group affiliation} of one or more other element declarations and whose ·substitution group· contains at least one element declaration other than itself is treated as if it were a choice group whose {min occurs} and {max occurs} are those of the particle, and whose {particles} consists of one particle with {min occurs} and {max occurs} of 1 for each of the declarations in its ·substitution group·.
Under Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup), the specification clarifies that:
For an element declaration particle to be a ·valid restriction· of a group particle (all, choice or sequence) a group particle of the variety corresponding to B's, with {min occurs} and {max occurs} of 1 and with {particles} consisting of a single particle the same as the element declaration must be a ·valid restriction· of the group as defined by Particle Derivation OK (All:All,Sequence:Sequence -- Recurse) (§3.9.6), Particle Derivation OK (Choice:Choice -- RecurseLax) (§3.9.6) or Particle Derivation OK (All:All,Sequence:Sequence -- Recurse) (§3.9.6), depending on whether the group is all, choice or sequence.
This creates the perverse situation where the invalid schema (above) is converted into the following:
<xs:complexType name="Test.Parent">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="representedOrganization" type="Organization.Organization" minOccurs="1" maxOccurs="1"/>
<xs:element name="scopingOrganization" type="Organization.Organization" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Test.Child">
<xs:complexContent>
<xs:restriction base="Test.Parent">
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="1">
<xs:element name="scopingOrganization" type="Organization.Organization" minOccurs="0" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
This schema passes the choice-level cardinality check in the Particle Derivation OK (Choice:Choice -- RecurseLax). However, it fails the test for the (nested) particles because the cardinality of the restricted item is larger than the cardinality of the matching particle in the base type.
NOTE: Parsers may report this as an issue in Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup). This is the section that contains instructions to treat the element as a choice and run the nested choice test. For example, XMLSpy reports:
rcase-RecurseAsIfGroup: <element name="scopingOrganization" minOccurs="0"> is not a valid restriction of model group particle <element ref="representedOrganization" minOccurs="0">.
If you have control over the deriving schema, you could overcome this issue by wrapping the element in a choice and moving the cardinality to this level.
I have the following XSD structure:
<xs:schema xmlns:ns="http://abc/">
...
<xs:element name="abc">
<xs:complexType>
<xs:sequence>
<xs:element ref="map"/>
</xs:sequence>
</xs:complexType>
</xs:element>
...
<xs:element name="map">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" type="ns:MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:unique name="entry">
<xs:selector xpath="entry"/>
<xs:field xpath="key"/>
</xs:unique>
</xs:element>
<xs:complexType name="MapEntryType">
<xs:sequence>
<xs:element name="key" type="xs:string"/>
<xs:element name="value" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
This is doing its job.
The map element now has to be called something different based on whichever is the wrapper, so the name is sometimes map, sometimes properties, sometimes options, etc.
Therefore I want to genericize the map element.
I tried doing the following:
Making map a xs:complexType and changing ref to type.
This resulted in xs:unique not being accepted and failed
Making map a xs:complexType, changing ref to type and moving the xs:unique constraint to the element definitions.
This worked but resulted in the XSD having a lot of xs:unique present in the document.
Isn't there a way to simply tell that I want a specific structure and it containing unique elements without having to repeat the unique constraint everywhere?
As Petru Gardea said in his answer
Both XSD 1.0 and 1.1 place the identity constraints under an element
So you have to add xs:unique to every element, but if you are using XSD 1.1 you can define only once a complete xs:unique and then in the rest of the elements use xs:unique ref="name". This is not valid for you as you are using XSD 1.0, but I let it here for future XSD 1.1 users that find this good question.
Example (namespaces removed for clarity):
<xs:element name="map">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" type="MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- Only completely defined once -->
<xs:unique name="uniqueEntry">
<xs:selector xpath="entry"/>
<xs:field xpath="key"/>
</xs:unique>
</xs:element>
<xs:element name="hashMap">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" type="MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- Referenced here and every other time -->
<xs:unique ref="uniqueEntry"/>
</xs:element>
Short answer, it is not possible. Both XSD 1.0 and 1.1 place the identity constraints under an element; a constraint cannot be globally defined, therefore there is no "reuse" per se, other than that of the enclosing element. Given your scenario (different element names for different needs) it is not possible to reuse.
I have a XSD with XML elements A, B, and C.
I would like these to appear in a parent element in this way:
A and B can appear any times, C only once, optionally.
The order does not matter, but A and B should ideally be "together",
(so it's rather (A*), C?, (B*) | (B*), C?, (A*)), but the "A and B together" is not necessary).
How can I achieve that with XSD?
Actual XSD what I have tried:
<!-- Hint -->
<xs:element name="hint">
<xs:complexType mixed="true">
<xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:choice>
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:choice>
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
But that gives me
cos-nonambig: <ns>:link and <ns>:link (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
Basically, the need is to have any mix of A, B, C, where C appears
only once.
XSD 1.1 Solution
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<xs:complexType name="SolutionType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="A"/>
<xs:element name="B"/>
<xs:element name="C"/>
</xs:choice>
<xs:assert test="count(c) <= 1"/>
</xs:complexType>
</xs:schema>
The above xs:assertion assumes that you mean "C appears at most once" but can easily be adjusted to require C to appear exactly once.
A and B can appear any times, C only once, optionally. The order does
not matter, but A and B should ideally be "together"
XSD 1.0 Solution
You'll have to impose an ordering to avoid violating Unique Particle Attribution:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="SolutionType">
<xs:sequence>
<xs:element name="A" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="C" minOccurs="0"/>
<xs:element name="B" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
At least this achieves your preference toward keeping A and B together.
The "Unique Particle Attribution" basically means that every element during validation needs to be deterministically assignable to certain XSD "branch". And that can be checked when validating the XSD.
I found out that the (only?) way to avoid abiguity is to list all combinations of A,B,C in a <xs:choice>, while setting minOccurs="1" as appropriate to break the ambiguity. That gives quite a few choices, but for 3 elements, still doable.
This is for the case where I leave 'C' in the beginning:
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="1"/>
<xs:choice>
<xs:sequence>
<xs:element ref="link" minOccurs="1" maxOccurs="unbounded" />
<xs:element ref="tag" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:sequence>
<xs:element ref="tag" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="link" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:sequence/>
</xs:choice>
</xs:sequence>
Not closing this question, I believe there's a better option even in XSD 1.0.
After importing a complextype in one xsd from another xsd, is it possible to have selected subelements of the complex type in the second xsd
What I mean is :
I have first xsd. -> AddressFile.xsd .In AddressFile.xsd, there is a complex type IndividualAddress, with 5 subelemnts. In the next xsd, Individual.xsd , I am referring to the complext type IndividualAddress in AddressFile.xsd. But in Individual.xsd, I just want DoorNO , StreetNum and State from the complex Type IndividualAddress directly . Is that possible. Is there any restrictions I can use.
AddressFile.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://abc/DP/Address">
<xs:complexType name="IndividualAddress">
<xs:annotation>
<xs:documentation>Address of an individual
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="DoorNO" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="StreetNum" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="State" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Country" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Pin" type="xs:String"
nillable="true" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Individual.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:address="http://abc/DP/Address"
targetNamespace="http://abc/DP/Individual">
<xs:import namespace="http://abc/DP/Address"
schemaLocation="AddressFile.xsd"/>
<xs:complexType name="Individual">
<xs:annotation>
<xs:documentation>Address of an individual
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Name" type="xs:String"
nillable="true" minOccurs="0"/>
<xs:element name="Age" type="xs:int"
nillable="true" minOccurs="0"/>
<xs:element name="DoorNO" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
<xs:element name="StreetNum" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
<xs:element name="State" type=" address:IndividualAddress "
nillable="true" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Your best approach depends on what you are trying to accomplish.
If you want XSD-aware tools to know that complex type Individual is derived from complex type IndividualAddress, you can derive the one from the other. You will need to do so in two steps: a restriction step to get rid of the unwanted child elements of the base type and then an extension step to add more elements, at the end. (Not at the beginning.)
If you just want to reuse the elements, the creator of the base schema has done the best job they can to hinder you, by making all the children of IndividualAddress local types, which cannot be referred to from elsewhere. If they wanted to make reuse easy, or even possible, they would (a) make the elements in question top-level elements, and/or possibly (b) use named model groups to package up groups of useful elements to be used together.
What I'm trying to do is, declare an parent element called "data", which are having 10 sub element of these one element are conditional.
My XSD is:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified" attributeFormDefault="unqualified" vc:minVersion="1.1">
<xs:element name="data" >
<xs:complexType>
<xs:sequence>
<xs:element name="sub_data" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all >
<xs:element ref="A"/>
<xs:element ref="B" minOccurs="0" maxOccurs="1"/>
<xs:element ref="C"/>
<xs:element ref="D"/>
<xs:element ref="E"/>
<xs:element ref="F"/>
<xs:element ref="G"/>
<xs:element ref="H"/>
<xs:element ref="I"/>
<xs:element ref="J"/>
<xs:element ref="K"/>
<xs:element ref="L"/>
<xs:element ref="M"/>
<xs:element ref="N"/>
<xs:element ref="element_group"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="status"/>
</xs:complexType>
</xs:element>
<xs:element name="O" type="xs:string" substitutionGroup="element_group">
<xs:element name="P" type="xs:string" substitutionGroup="element_group">
<xs:element name="Q" type="xs:string" substitutionGroup="element_group">
</xs:schema>
Requirement is:
All element from A to N are appearing in any order.
Element P,Q and R is also part of data but only one element appear from among 3. Order is also any.
More important I have cover 1st and 2nd point but I want one more restriction is that only and only four element will be become the part of <data> that means element count from <A> to <Q> is exact four,
Combination can any of them from <A> to <Q> but final count is only four, please help me.
Now currently i am unable to set maxOccures in <all> , it not compiling the xsd after setting maxOccures.
The simplest way to handle this is probably to use XSD 1.1 and use an assertion on the parent to specify that there must be exactly (or at most) four children. You will also need to make each child of the all-group optional, since thirteen of them will not appear.
The best way might be to redesign your XML to work better with your schema language instead of fighting it. It's hard to give advice on that, though, since your example is abstract enough to make it unclear why you are imposing the requirements you mention.