XSD: Restricting a substitutionGroup - xsd

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.

Related

<xs:all minOccurs="0" still requires the elements to exist

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.

Unique constraint on a complexType instead of an element

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.

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

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.

XSD complexType definition without indicators

if i want to define a complex type, i can go
<xs:complexType name="personinfo">
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
or, i can replace the
<xs:sequence> ... </xs:sequence>
tag in the above with
<xs:all> ... </xs:all>
or
<xs:choice> ... </xs:choice>
and it validates.
However, these are imposing restrictions on the order/occurrence of the elements.
Is there a way to define a complex element without any of these indicators?
Been "inspired" with
<xs:complexType name="personinfo2">
<xs:complexContent>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:complexContent>
</xs:complexType>
so far, but didn't work.
You really should read a tutorial on XSD.
No, you cannot define a content model without specifying (explicitly or implicitly) one of xs:sequence, xs:choice, or xs:all.
If you want to make no restrictions on the sequence or number of occurrences of your child elements, then what you probably want is:
<xs:complexType name="sample">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="e1" type="xs:string"/>
<xs:element name="e2" type="xs:string"/>
</xs:choice>
</xs:complexType>
This allows any number of e1 and e2 children, in any order. If you find that you don't want any valid elements of type personinfo to contain 37 lastname elements and 36 firstname elements, in alternation, then you have discovered something about what you do and don't want.

XSD - Override element

I've a base class, marked as abstract:
<!-- TYPE: BASE CLASS -->
<xs:complexType name="BaseClass" abstract="true">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="implementation" type="BaseClass" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
Now the class that inherits BaseClass and overrides 'implementation' with null:
<xs:complexType name="MyClass">
<xs:complexContent>
<xs:extension base="BaseClass"/>
</xs:complexContent>
</xs:complexType>
I've tried this but is invalid:
<xs:complexType name="MyClass">
<xs:complexContent>
<xs:extension base="BaseClass">
<xs:sequence>
<xs:element name="implementation" fixed="xs:nil"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Is there a way to do this?
Marking something as abstract in XSD schema basically means that it cannot appear in an instance document. It should be used with the substitutionGroup attribute.
For example
<xs:element name="replaceme" abstract="true" />
<xs:element name="replacement1" substitutionGroup="replaceme" />
<xs:element name="replacement2" substitutionGroup="replaceme" />
This means that in an instance document you would be forced to use either a "replacement1" or a "replacement2" element, ie the xsd is forcing you to substitute the "replaceme" element with one of the replacements from the substitution group.
So to achieve what you want you need to create a substitution group consisting of the types you want to use instead of your base type. I am not sure this is possible with complex types but give it a go.

Resources