Working with XML 1.1 in Oxygen XML Editor version 23.1. Originally I wandted to make an xsd schema that can have a complexType-element with a child-element, an extension and a bunch of attributes. A first possible solution I was able to get here but figured out it didn't fit to my problem, because the child-element itself consists of several elements and attributes which makes the original approach invalid, causing the error message: "The content type of a derived type and that of its base must both be mixed or both be element-only. Type 'complexTypeContent' is mixed, but its base type is not".
To my problem itself: The aim is for the child-element random
to only be used when the attribute until
has the value 'random'. So in the end a XML-file like this should be valid:
<instruction>
<type repeat='1' until='random'><random start='1' end='6'/>Dice Roll</type>
</instruction>
Instead - if the attribute until
has not the value "random" - the element random must not be allowed. So something like this should be forbidden:
<instruction>
<type repeat='1' until='2'><random start='1' end='6'/>Dice Roll</type>
</instruction>
With help from here I was able to modify my xsd-scheme to something like this. But as already stated, it doesn't compile without an error message:
<xs:element name="root">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="instruction" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="type">
<xs:alternative test="@until = 'random'" type="complexTypeContent"/>
<xs:alternative type="simpleTypeContent"/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="complexTypeContent" mixed="true">
<xs:complexContent>
<xs:extension base="simpleTypeContent">
<xs:sequence>
<xs:element name="random" type="random" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="random">
<xs:attribute name="start">
<xs:simpleType>
<xs:restriction base="xs:integer"/>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="end">
<xs:simpleType>
<xs:restriction base="xs:integer"/>
</xs:simpleType>
</xs:attribute>
<xs:assert test="@start le @end"/>
</xs:complexType>
<xs:complexType name="simpleTypeContent" mixed="true">
<xs:simpleContent>
<xs:extension base="type2">
<xs:attribute name="until">
<xs:simpleType>
<xs:union memberTypes="type2 annotation xs:integer until"/>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="condition">
<xs:simpleType>
<xs:union memberTypes="type2 annotation extended"/>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="repeat" type='xs:integer'/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="type2">
<xs:restriction base="xs:string">
<xs:enumeration value="Dice Roll"/>
<xs:enumeration value="Wait"/>
<xs:enumeration value="Repeat"/>
<xs:enumeration value="Double Roll"/>
<xs:enumeration value="Instruction"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="until">
<xs:restriction base="xs:string">
<xs:enumeration value="end"/>
<xs:enumeration value="random"/>
<xs:enumeration value="Instruction"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="annotation">
<xs:restriction base="xs:string">
<xs:enumeration value="rolltwice"/>
<xs:enumeration value="halfcount"/>
<xs:enumeration value="doublecount"/>
<xs:enumeration value="roll-"/>
<xs:enumeration value="roll+"/>
<xs:enumeration value="numberChange"/>
<xs:enumeration value="NoNumberChange"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="extended">
<xs:restriction base="xs:string">
<xs:enumeration value="noRolling"/>
<xs:enumeration value="noEven"/>
<xs:enumeration value="noUneven"/>
<xs:enumeration value="stopped"/>
</xs:restriction>
</xs:simpleType>
The error messages I had now all imply that this solution is invalid because of the not mixed content of simpleTypeContent
or because it has simpleContent which cannot be derived from the complex content of complexTypeContent
. So, how do I get it working? I cannot figure out any working solution for the problem I am facing.
As far as I understand, XSD (not even 1.1) doesn't offer a way to restrict the mixed content text to some simple type, so the only way, if you really need that single element together with a certain list of values seems to be an assertion; that means, unfortunately, you need to duplicate the values you also want for an attribute.
So some (slightly adapted, see my comment about the `@until = 'random' check) sample schema would be
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">
<xs:element name="root">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="instruction" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="type">
<xs:alternative test="@until = 'random'" type="complexTypeContent"/>
<xs:alternative type="simpleTypeContent"/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="complexTypeContent" mixed="true">
<xs:complexContent>
<xs:extension base="simpleTypeContent">
<xs:sequence>
<xs:element name="random" type="random" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="random">
<xs:attribute name="start">
<xs:simpleType>
<xs:restriction base="xs:integer"/>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="end">
<xs:simpleType>
<xs:restriction base="xs:integer"/>
</xs:simpleType>
</xs:attribute>
<xs:assert test="@start le @end"/>
</xs:complexType>
<xs:complexType name="simpleTypeContent" mixed="true">
<xs:attribute name="until">
<xs:simpleType>
<xs:union memberTypes="type2 annotation xs:integer until"/>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="condition">
<xs:simpleType>
<xs:union memberTypes="type2 annotation extended"/>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="repeat" type='xs:integer'/>
<xs:assert test=". = ('Dice Roll', 'Wait', 'Repeat', 'Double Roll', 'Instruction')"/>
</xs:complexType>
<xs:simpleType name="type2">
<xs:restriction base="xs:string">
<xs:enumeration value="Dice Roll"/>
<xs:enumeration value="Wait"/>
<xs:enumeration value="Repeat"/>
<xs:enumeration value="Double Roll"/>
<xs:enumeration value="Instruction"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="until">
<xs:restriction base="xs:string">
<xs:enumeration value="end"/>
<xs:enumeration value="random"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="annotation">
<xs:restriction base="xs:string">
<xs:enumeration value="rolltwice"/>
<xs:enumeration value="halfcount"/>
<xs:enumeration value="doublecount"/>
<xs:enumeration value="roll-"/>
<xs:enumeration value="roll+"/>
<xs:enumeration value="numberChange"/>
<xs:enumeration value="NoNumberChange"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="extended">
<xs:restriction base="xs:string">
<xs:enumeration value="noRolling"/>
<xs:enumeration value="noEven"/>
<xs:enumeration value="noUneven"/>
<xs:enumeration value="stopped"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
and that then makes the first instruction
in below sample (also slightly adapted as there was a spelling difference between the schema and the sample (Dice roll
vs. Dice Roll
) in your snippets) valid while the second is invalid:
<root>
<instruction>
<type repeat='1' until='random'><random start='1' end='6'/>Dice Roll</type>
</instruction>
<instruction>
<type repeat='1' until='2'><random start='1' end='6'/>Dice Roll</type>
</instruction>
</root>