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.
Related
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>
<xs:element name="featureTests">
<xs:complexType>
<xs:sequence>
<xs:element name="test" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="status">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="not run"/>
<xs:enumeration value="passed"/>
<xs:enumeration value="failed"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="summary" type="xs:string"/>
<xs:sequence>
<xs:element name="step" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
I'm using the above XSD to validate my xml files which works fine all except for the status tag enumeration restriction.
if I do this:
<status>
not run <!--OR passed OR failed-->
</status>
Validation fails saying that it must contain either [not run,passed,failed]
Could you tell me where I am going wrong?
Thanks
The problem comes about because of the spaces/tabs in the xml doc surrounding the enumerated value ie having this " not run " instead of this "not run".
to solve this I changed the XSD file to use the token type rather than the string type to remove the leading and trailing whitespace characters:
<xs:restriction base="xs:token">
<xs:enumeration value="not run"/>
<xs:enumeration value="passed"/>
<xs:enumeration value="failed"/>
</xs:restriction>
Of interest is the following xml child element:
<optInItem type='MARKETING_EMAILS'>NO</optInItem>
I'd like to enumerate possible values (assume 2 possible values) for attribute 'type' and enumerate possible values for the text value of optInItem (values could be Yes | No). I am starting with the following xsd but am not sure how to add in the two separate enumerations.
<xs:element name="optInItem" maxOccurs="2" minOccurs="2">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="type" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
Any suggestions/pointers would be appreciated.
thanks
After many iterations, it looks like the following does the trick:
<xs:element name="account">
<xs:complexType>
<xs:sequence>
<xs:element type="optInItemType" name="optInItem" maxOccurs="2" minOccurs="2">
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="optInItemType">
<xs:simpleContent>
<xs:extension base="elementOptInItemType">
<xs:attribute name="type" type="attrOptInItemType"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="elementOptInItemType">
<xs:restriction base="xs:string">
<xs:enumeration value="YES"/>
<xs:enumeration value="NO"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="attrOptInItemType">
<xs:restriction base="xs:string">
<xs:enumeration value="MARKETING_EMAILS"/>
<xs:enumeration value="UPDATE_NOTIFICATIONS"/>
</xs:restriction>
</xs:simpleType>
That was a more complicated than I thought it would be. The simpleContent
extension base allowed a user defined type and thus was the key to pulling it
all together.
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>
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