I have difficulty in writing a schema in XSD1.1. XML structure is already defined and used by many teams, so changing the xml is not an option to me. May be I can't explain everything I tried here. XSD has evolved so much since start. I just hope some ppl can understand the problem clearly.. Would be great if someone can share their way of solving this problems..
How XML looks like (in simplified format)
<Node>
<Create Type="A">
<Attr Name="Type1" Val="123"/>
<Attr Name="Type2" Val="Water"/>
<Attr Name="Type3" Val="2019-12-01T08:00:00"/>
</Create>
<Create Type="B">
<Attr Name="TypeM" Val="OB123"/>
<Attr Name="Type2" Val="Fire"/>
<Attr Name="TypeK" Val="2019-12-01T08:00:00"/>
<Attr Name="TypeN" Val="11.567"/>
</Create>
</Node>
Problem:
Based on "Type" attribute in Element<Create> - Number of <Attr> Elements changes (There are 80 types). Each Type can allow specific set of child attr. In above e.g, when Type = A, it can have only 3 children and specifically Type1, Type2 and Type3.
Based on value of "Name" attribute in Element <Attr> , attribute "Val" can have range of Values. In Xml shown above, Type2 can have {Fire, Water}
Based on value of "Name" attribute in Element<Attr> , define the type of second attribute "Val" which can be (date,integer, string, float etc)
The XSD I am trying to write looks something like this (actual XSD and XML are huge)..
<xs:element name="Node" type="NodeType"/>
<xs:complexType name="NodeType">
<xs:sequence>
<xs:element name="Create">
<xs:alternative test="@Type = 'A'" type="AType"/>
<xs:alternative test="@Type = 'B'" type="BType"/>
<xs:alternative type="xs:error"/>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AType">
<xs:sequence>
<xs:element name="Attr">
<xs:alternative test="@Name = 'Type1'" type="AttrType1"/>
<xs:alternative test="@Name = 'Type2'" type="AttrType2"/>
<xs:alternative test="@Name = 'Type3'" type="AttrType3"/>
<!--<xs:alternative type="xs:error"/> This line gives error while same line above passes validation-->
</xs:element>
</xs:sequence>
<xs:attribute name="Type" use="required" type="AllowedTypes"/> <!-- AllowedTypes is an enum of 80 values-->
<xs:assert test="(@Type = 'A')"/>
</xs:complexType>
<xs:complexType name="AttrType1">
<xs:attribute name="Name" type="xs:string"/>
<xs:attribute name="Val" type="xs:integer"/>
</xs:complexType>
<xs:complexType name="AttrType2">
<xs:attribute name="Name" type="xs:string"/>
<xs:attribute name="Val" type="xs:string"/>
<xs:assert test="(@Val = 'Fire' or @Val='Water')"/>
</xs:complexType>
<xs:complexType name="AttrType3">
<xs:attribute name="Name" type="xs:string"/>
<xs:attribute name="Val" type="xs:dateTime"/>
</xs:complexType>
<!-- Similarly written for BType -->
Thanks to this post - How to make type depend on attribute value using Conditional Type Assignment.
After spending days.. I am able to solve 3 problems (one at a time) stated above.. I am facing issue when I tried to club all 3 solutions in one nice compact xsd.
For Eg.. When I try to solve Problem 3, solution to problem 1 is messed up.
<Node>
<Create Type="A">
<Attr Name="Type1" Val="123"/>
<Attr Name="Type2" Val="Water"/>
<Attr Name="TypeZ" Val="2019-12-01T08:00:00"/>
</Create>
</Node>
<!-- I want XSD to throw error saying TypeZ is not allowed -->