Problem with restriction in xsd complex type inheritance - xsd

I have the a little problem with the xsd below. I have created a type of vaultobject with a type attribute that can have any value in a enumeration. Then I derived VaultServiceObject from vaultobject en set a restriction to limit type to a fixed value for the derived object.
The editor (liquid-xml) design service seems to understand this and displays correctly, but the text editor marks the line 26 as and error.
<xs:attribute name="Type" fixed="ServiceConfiguration" type="xs:string" use="required">
Saying "Error Invalid attribute restriction. Derived attribute's type is not a valid restriction of the base attribute's type." So from this I guess "xs:string" is wrong. But I cannot figure out what type I should use.
Hopefully there is someone more experienced with XSD out there.
p.s I cobbled xsd below together from several other similar stackoverflow questions, but they do not supply this exact combination and its solution. So please do not point to those without explaining what I am looking for.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid Studio 2020 (https://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="VaultObject">
<xs:sequence>
<xs:annotation>
<xs:documentation>Allows for derived object to have a sequence of elements</xs:documentation>
</xs:annotation>
</xs:sequence>
<xs:attribute name="Type" use="required">
<xs:annotation>
<xs:documentation>This is the list of possible vault objects. Derived objects need to lock this down to the object type the represent.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Merge" />
<xs:enumeration value="ServiceConfiguration" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:anyAttribute />
</xs:complexType>
<xs:complexType name="VaultServiceConfigurationObject">
<xs:complexContent>
<xs:restriction xmlns:q2="http://www.it-workz.nl/IDM" base="VaultObject">
<xs:attribute name="Type" fixed="ServiceConfiguration" type="xs:string" use="required">
<xs:annotation>
<xs:documentation xml:lang="EN">This property is inherited from VaultObject, but is locked down to the fixed value of "ServiceConfiguration"</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ServiceType">
<xs:annotation>
<xs:documentation xml:lang="EN">The list of possible service types we support. Derived service definitions need to lock this down to a single value in their own type.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="SystemA" />
<xs:enumeration value="SystemB" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Name" type="xs:string" use="required">
<xs:annotation>
<xs:documentation xml:lang="EN">Every service needs to be uniquely named. Even between different service types.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:schema>

You can do this by breaking the 'Type' enum out into it's own SimpleType.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid Studio 2020 (https://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="VaultObjectType">
<xs:restriction base="xs:string">
<xs:enumeration value="Merge" />
<xs:enumeration value="ServiceConfiguration" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="VaultObject">
<xs:sequence>
<xs:annotation>
<xs:documentation>Allows for derived object to have a sequence of elements</xs:documentation>
</xs:annotation>
</xs:sequence>
<xs:attribute name="Type" type="VaultObjectType" use="required">
<xs:annotation>
<xs:documentation>This is the list of possible vault objects. Derived objects need to lock this down to the object type the represent.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:anyAttribute />
</xs:complexType>
<xs:complexType name="VaultServiceConfigurationObject">
<xs:complexContent>
<xs:restriction xmlns:q2="http://www.it-workz.nl/IDM" base="VaultObject">
<xs:attribute name="Type" fixed="ServiceConfiguration" type="VaultObjectType" use="required">
<xs:annotation>
<xs:documentation xml:lang="EN">This property is inherited from VaultObject, but is locked down to the fixed value of "ServiceConfiguration"</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ServiceType">
<xs:annotation>
<xs:documentation xml:lang="EN">The list of possible service types we support. Derived service definitions need to lock this down to a single value in their own type.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="SystemA" />
<xs:enumeration value="SystemB" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="Name" type="xs:string" use="required">
<xs:annotation>
<xs:documentation xml:lang="EN">Every service needs to be uniquely named. Even between different service types.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
</xs:schema>

Related

Constraining localized enum values by xsd

What I'm trying to achieve is build an xml structure that will be further used to generate event classes. These events that will be further used for user facing logs.
These events may be simple messages or may contain parameters which can either be base types or enums, under the condition that the any enum type must be local to the event class that uses it.
Let's take the example of an event that reports the temperature of something. It would look somewhat like this:
<SoftwareEvent
EventID="126.042.027"
NiceID="InstrumentControl.TemperatureEvent"
Message="The temperature of the cooling element is {0} of {1}-{2}°C.">
<enumType name="ElementTemperatureStatus" base="int">
<enumValue value="InRange" EnglishMessage="within the acceptable range" />
<enumValue value="OutOfRange" EnglishMessage="outside the acceptable range" />
<enumValue value="AtLowerRangeLimit" EnglishMessage="near the lower limit of the acceptable range" />
<enumValue value="AtUpperRangeLimit" EnglishMessage="near the upper limit of the acceptable range" />
</enumType>
<Parameters>
<Parameter name="temperatureStatus" type="enumeration" enumerationType="ElementTemperatureStatus"/>
<Partameter name="rangeLowerLimit" type="double"/>
<Partameter name="rangeUpperLimit" type="double"/>
</Parameters>
and this xml could be used to generate the event class and related localizable resources.
I also want to use a schema(attached bellow) to enforce this structure and I've been mostly successful however I do have a problem that I can't quite fix.
I would like to know if it's possible to use the xsd schema of such an xml to enforce the enumerationType type of the first event to be one of the enumTypes declared above in the scope of the same SoftwareEvent. And if so, how would one go about doing this?
Here is the xsd I have a this point
<xs:element name="SoftwareEvents">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="SoftwareEvent" >
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="enumType" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="enumValue" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="value" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z_][a-zA-Z0-9_]*"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="EnglishMessage" use="required">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z_][a-zA-Z0-9_]*"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="int"/>
<xs:enumeration value="byte"/>
<xs:enumeration value="long"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="Parameters" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Partameter" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z_][a-zA-Z0-9_]*"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="int"/>
<xs:enumeration value="double"/>
<xs:enumeration value="string"/>
<xs:enumeration value="long"/>
<xs:enumeration value="enumeration"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="enumerationType" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z_][a-zA-Z0-9_]*"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="EventID" use="required" >
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[\d]{3}.[\d]{3}.[\d]{3}"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="NiceID" type="xs:string" use="required" />
<xs:attribute name="Message" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Try defining SoftwareEvent/EnumType/EnumValue/#value as a key (scoped, I guess, to SoftwareEvent) and SoftwareEvent/Parameters/Partameter (sic) as a keyref.

How to Extend a XSD Restriction/Pattern Value

I am trying to restrict the values for two Elements that can share (most of) the same attribute 'type' values. I'd like to be able to extend those values for one of the Elements (see sample code below -- the 'End' element's 'Value' attribute can have the same entries as the 'Start' element's 'Value' attribute, but there can be additional values). I don't think my solution in the example is correct; is there a simple solution that I can follow?
<xsd:simpleType name="StartAndEndTypeType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="(value1|value2|value3"/>
</xsd:restriction>
</xsd:simpleType>
<xs:element name="Start">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:float">
<xs:attribute name="Value" type="StartAndEndTypeType"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="End">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:float">
<xs:attribute name="Value" type="StartAndEndTypeType|value4"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
This can be done in a number of ways.
Note I've changed your pattern facet to an enumeration as it works better for the example (but a pattern facet could be put back if required)
1 - Restricting a type
The StartAndEndTypeType contains all the values required, and then you restrict the ones you don't want in the StartType.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid Studio 2019 BETA (https://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="StartAndEndTypeType">
<xs:restriction base="xs:string">
<xs:enumeration value="value1" />
<xs:enumeration value="value2" />
<xs:enumeration value="value3" />
<xs:enumeration value="value4" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="StartType">
<xs:restriction base="StartAndEndTypeType">
<xs:enumeration value="value1" />
<xs:enumeration value="value2" />
<xs:enumeration value="value3" />
</xs:restriction>
</xs:simpleType>
<xs:element name="Start">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:float">
<xs:attribute name="Value" type="StartType" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="End">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:float">
<xs:attribute name="Value" type="StartAndEndTypeType" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
2 - Extend the base definition using a union
You define the base type StartAndEndTypeType, then add to it the additional values you want to allow using an xs:union.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid Studio 2019 BETA (https://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="StartAndEndTypeType">
<xs:restriction base="xs:string">
<xs:enumeration value="value1" />
<xs:enumeration value="value2" />
<xs:enumeration value="value3" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="EndType">
<xs:union memberTypes="StartAndEndTypeType">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="value4" />
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
<xs:element name="Start">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:float">
<xs:attribute name="Value" type="StartAndEndTypeType" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="End">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:float">
<xs:attribute name="Value" type="EndType" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>

Element-Mandatory Attribute declaration in XSD Schema:

I want to declare an element to be included in a complex type declaration, and the element has a mandatory attribute: "option=MyOption", but the value of the "option" attribute could be anything, depending on the context.
That is: the attribute "option" with some unknown value should be mandatory in any document using the complex type containing this element.
Example:
<xs:element name="SpecialOption" type="xs:string"/>
<xs:complexType name="SpecialOptions">
<xs:sequence>
<xs:element ref="SpecialOption" minOccurs="1" maxOccurs="100"/>
<xs:element ref="XXX"/>
</xs:sequence>
</xs:complexType>
In this case the "SpecialOption" element in the complex type "SpecialOptions" should have this mandatory attribute.
I don't know how to declare a mandatory attribute for an element in XSD, or how to specify that the attribute must have a value that is not yet known.
You need to modify the definition of the "SpecialOption" element to include the required attribute. Update this code:
<xs:element name="SpecialOption" type="xs:string"/>
to this:
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
With this change your complex type will contain the required "Option" attribute on all instances of the "SpecialOption" element in the "SpecialOptions" complex type. Declaring the "Option" attribute to be of type xs:string will allow any value to be passed in this field.
1) This is a simple required string attribute
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
2) To require exactly one of a list of allowed values:
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="DE"/>
<xs:enumeration value="EN"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
3) One can use a range as a restriction, like in the example below.
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" use="required">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="95"/>
<xs:maxInclusive value="137"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
4) Below, the attribute is declared as a list containing decimal values. This allows an attribute to contain a subset of the specified values, e.g. Option="6 77 95".
<xs:simpleType name="Items">
<xs:restriction base="xs:decimal">
<xs:enumeration value="137"/>
<xs:enumeration value="95"/>
<xs:enumeration value="6"/>
<xs:enumeration value="77"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" use="required">
<xs:simpleType>
<xs:list itemType="Items"/>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
5) Here the attribute is declared optional, but provided with a default value ("test"), which is sometimes sufficient:
<xs:element name="SpecialOption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Option" type="xs:string" use="optional" default="test"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
To mark an attribute as mandatory you use <xs:attribute use="required" />.
As for type, you have a choice of the built-in XSD types (xs:string etc), or you can define your own <xs:simpleType /> and use that.
UPDATE
I am not certain what you mean by the attribute must have a value that is not yet known. Does this mean that the value is a string, but can be any string? Or a decimal?
Because it's an attribute value we are talking about you are restricted to using the built-in XSD types, or defining your own xs:simpleType type based on one of the built-in types. This is where you can apply more stringent rules to the allowed value, for example by extending xs:string and adding a regular expression constraint to allowed values.
<xsd:simpleType name="UKDate">
<xsd:restriction base="xsd:string">
<xsd:pattern value="(0?[1-9]|[12][0-9]|3[01])[- /.](0?[1-9]|1[012])[- /.](19|20)\d\d"/>
</xsd:restriction>
</xsd:simpleType>
However, if there is absolutely no way of knowing what value will be used then you have the well known temporal paradox whereby you cannot restrict something at design-time to a value you only know at run-time. In this instance, surely it is only necessary to specify that the attribute must at least be present?
<xs:attribute use="required" />
Hope this answers your question a little more clearly.
Simply you can do it as the following
<xs:element name="SpecialOption">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="replace"/>
<xs:minLength value="1"></xs:minLength>
</xs:restriction>
</xs:simpleType>
</xs:element>
by this code you enforce to insert a value on the xml tag and also the white space restriction will handle to remove the white space from the xml tag.

XSD Definition for Enumerated Value

I'm stuck trying to define an XSD containing a field that can have only one of the following three values:
Green
Red
Blue
Essentially, I want to define a strict enumeration at the Schema level.
My First attempt appears wrong and I'm not sure about the "right" way to fix it.
<xs:element name="color">
<xs:complexType>
<xs:choice>
<xs:element name="green"/>
<xs:element name="red"/>
<xs:element name="blue"/>
</xs:choice>
</xs:complexType>
</xs:element>
By using an automatic XML generator, it treats those element names as string objects:
<xs0:color>
<xs0:green>text</xs0:green>
</xs0:color>
You can define an enumeration within the context of a simpleType.
<xs:simpleType name="color" final="restriction" >
<xs:restriction base="xs:string">
<xs:enumeration value="green" />
<xs:enumeration value="red" />
<xs:enumeration value="blue" />
</xs:restriction>
</xs:simpleType>
<xs:element name="SomeElement">
<xs:complexType>
<xs:sequence>
<xs:element name="Color" type="color" />
</xs:sequence>
</xs:complexType>
</xs:element>
This solution worked for me:
<xs:element name="color">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="green"/>
<xs:enumeration value="red"/>
<xs:enumeration value="blue"/>
</xs:restriction>
</xs:simpleType>
</xs:element>

XSD complains with "Multiple elements with name 'B', with different types, appear in the model group."

I have the following XSD:
<xs:complexType name="typeBroken">
<xs:choice>
<xs:element name="B">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="FOO|BAR" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:sequence>
<xs:element name="A">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="5" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="B">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="3" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:choice>
</xs:complexType>
So, I would like the presence of 'A' to make 'B' to have a different validation. Is this possible? For example:
<test><B>FOO</B></test>
<test><A>HELLO</A><B>BAZ</B><test>
Should both validate. While:
<test><B>BAZ</B></test>
Should NOT validate. However, I am getting from xsd:
cos-element-consistent: Error for type 'typeBroken'. Multiple elements with name 'B', with different types, appear in the model group.
Do I understand your requirements correctly? You want to have a <B>...</B> and optionally an <A>....</A> before that (but not required)?
How about this schema then?
<xs:complexType name="typeBroken">
<xs:sequence>
<xs:element name="A" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="5" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="B">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="FOO|BAR" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:choice>
</xs:complexType>
Define a sequence where the first element, <A>, is optional (minOccurs="0") while the second one is not optional.
Does that solve your requirement?
Marc

Resources