How to define Enumeration Constants in XSD? - xsd

I was looking to add system defined constants through an XSD. Here is a complex type that I have defined.
<xs:complexType name="app_job">
<xs:sequence>
<xs:element name="id" type="xs:string" minOccurs="1"/>
<xs:element name="cron" type="xs:string" minOccurs="1"/>
<xs:element name="description" type="xs:string" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
I am looking for adding system defined constants like
DAILY (1, "0 0 0 * * ?", "Daily Job")
HOURLY (2, "0 0 0/1 * * ?", "Hourly Job")
I was trying enumeration here
<xs:simpleType name="app_jobs">
<xs:restriction base="app_job">
<xs:enumeration id="1" cron="0 0 0 * * ?" description="Daily Job"/>
</xs:restriction>
</xs:simpleType>
But that does not seem right. Is there any way instance of the complex type with predefined values can be defined in same schema so that xsd2java can convert it to Java enum and I can use it in application? Instead of hand writing the enum, I wanted to source it from XSD.
Thanks in advance

Related

JAXB: xjc and fixed values for attributes of derived types

I'm trying to create an xsd with a type hierarchy.
What I'm hoping to archieve is that the subtypes fill the base type's attributes with a certain value.
This is my best result:
<xs:complexType name="base_type">
<xs:attribute name="att" use="required" type="xs:string" />
</xs:complexType>
<xs:complexType name="type1_t">
<xs:complexContent>
<xs:restriction base="base_type">
<xs:attribute name="att" fixed="value1" use="required" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="type2_t">
<xs:complexContent>
<xs:restriction base="base_type">
<xs:attribute name="att" fixed="value2" use="required" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
The "att" attribute is made available by base_type, and in elements of type1_t and type2_t, I'd like them set to "value1" and "value2", respectively.
The container element looks like this:
<xs:element name="root">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="type1" type="type1_t" />
<xs:element name="type2" type="type2_t" />
</xs:choice>
</xs:complexType>
</xs:element>
Now I'm running xjc to generate Java classes for this code, but the "fixed" attribute is not represented in what I get in the Type1T.java, which consists only of
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "type1_t")
public class Type1T extends BaseType { }
I would have expected
{
#Override public String getAtt() { return "value1"; }
}
?
That is (almost) what gets generated when the type is generated by itself (ie not as an extension of a base type).
I'm I doing something wrong? Is what I'm trying to do just not possible?
My goal is to automatically generate all java code from xsd; otherwise I suppose a way to implement this would be to code the fixed values in the created ObjectFactory methods for each class manually. However, then I would need to prevent ObjectFactory from getting generated every time...
Any hints? Tips? Thoughts?

XML schema for element whose simple type is driven by an attribute

I want to write an XML schema (xsd 1.1) for a document containing options. Each option has a name and a type (like boolean, integer, string, etc ...) and a datum matching that type. The list of types is fixed, but quiet long. (Only 3 are listed in listing 3 for simplicity.)
How do I do this without a ridiculous amount of repetition?
Use case 1
Here is a valid document for this schema..
Listing 1:
<abc:options>
<abc:option name="is-enabled" type="boolean">false</abc:option>
<abc:option name="wing-span" type="float">1.2</abc:option>
</abc:options>
Use case 2
This document is not valid for this schema because the simple type bit is wrong for the #type attribute.
<abc:options>
<abc:option name="is-enabled" type="boolean">24</abc:option>
<abc:option name="wing-span" type="float">this-is-not-a-number!</abc:option>
</abc:options>
What I have tried so far ...
Listing 3 is my attempt so far. But it is bad because I have to re-declare the #name attribute for each datum type. Is there a better solution? That is to say, one where I don't have to re-declare the #name attribute for each possible datum type.
Listing 3:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:abc="http://www.example.com"
targetNamespace="http://www.example.com"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="options">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="abc:option" type="option-Type"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="option-Datum-Type">
<xs:restriction base="xs:string">
<xs:enumeration value="boolean"/>
<xs:enumeration value="integer"/>
<xs:enumeration value="float"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="option-Type-boolean">
<xs:simpleContent>
<xs:extension base="xs:boolean">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="abc:option-Datum-Type" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="option-Type-string">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="abc:option-Datum-Type" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="option-Type-float">
<xs:simpleContent>
<xs:extension base="xs:double">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="abc:option-Datum-Type" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="option-Type">
<xs:alternative test="#type='boolean'" type="abc:option-Type-boolean"/>
<xs:alternative test="#type='string'" type="abc:option-Type-string" />
<xs:alternative test="#type='float'" type="abc:option-Type-float" />
<xs:alternative type="xs:error"/>
</xs:complexType>
</xs:schema>
If the type can only be one of the atomic types you can use xs:assert like this:
<xs:complexType name="option-Type">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="xs:string" use="required" />
<xs:assert
test="if (#type='boolean') then . castable as xs:boolean
else if (#type='float') then . castable as xs:float
else if (#type='int') then . castable as xs:int
else if (#type='string') then . castable as xs:string
else false()"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
Notes:
You don't need to declare any new type. If you want you can even also skip the declaration of the enumeration.
Using this approach you need a new line for every new possible type (you don't really need a new line but it is easy to read with every type in a different line).
You can use text() instead of . if you found it to be more clear
Notice how simply this approach would be if XPath 2.0 had an eval function similar to javascript and other languages eval function:
<xs:assert test="eval(text() || ' castable as xs:' || #type)"/>
I though an eval/parse function was going to be added to XPath 3.0 spec but I think it finally has not been added.
Unlike instance of you cannot use lists (*,+) other than ? with castable as operator. You can only use atomic types using this approach.
Cast to string string should always succed as the type is declared as xs:string.

XSD: Different Restriction by Attribute Values

I'm new in XSD and have the following question, thanks a lot for your help!
Suppose I have the xml:
<DataGroup>
<Data name="name">Jane</Data>
<Data name="age">50</Data>
<Data name="state>MA</Data>
<Data name="zipcode">01000</Data>
</DataGroup>
I'd like to put restriction on:
when the attribute name equals to "age", the value of should be an integer and >20,
when the attribute name equals to "state", the value of should be two letters.
when the attribute name equals to "zip code", the value of should be \d{5}.
Can not modify the xml, any idea?
Thanks!
Using XSD 1.1 you can declare alternative types for each situation. Additionally you can restrict the number of <Data> elements to exactly four, and add an assertion to guarantee that each different attribute occurs exactly once:
<xs:element name="DataGroup">
<xs:complexType>
<xs:sequence>
<xs:element name="Data" maxOccurs="4" minOccurs="4">
<xs:alternative type="NameData" test="#name='name'" />
<xs:alternative type="AgeData" test="#name='age'" />
<xs:alternative type="ZipData" test="#name='zipcode'"/>
<xs:alternative type="StateData" test="#name='state'"/>
</xs:element>
</xs:sequence>
<xs:assert test="Data/#name='name' and Data/#name='age' and Data/#name='zipcode' and Data/#name='state'"></xs:assert>
</xs:complexType>
</xs:element>
Since <Data> is a simple type, you need to declare the attribute as an extension of each type:
<xs:complexType name="NameData">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="AgeData">
<xs:simpleContent>
<xs:extension base="AgeType">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ZipData">
<xs:simpleContent>
<xs:extension base="ZipType">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="StateData">
<xs:simpleContent>
<xs:extension base="StateType">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
The restrictions you declare in the types which are base for the simple types:
<xs:simpleType name="AgeType">
<xs:restriction base="xs:integer">
<xs:minExclusive value="20"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="StateType">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{2}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ZipType">
<xs:restriction base="xs:string">
<xs:pattern value="\d{5}"/>
</xs:restriction>
</xs:simpleType>
This will validate your file with the restrictions you require.

Multiple elements in Xml Schema

I have a schema, where there are 3 elements and these 3 elements still have more sub elements. Lets name 1st element as Header, 2nd one as record, 2rd one as footer.
There is one occurence of header, multiple occurences of record and one occurence of footer again.
so the input to schema looks like
header
record..
record..
...
..
footer
now my problem is . my schema is defined like this
<xs:element minOccurs="1" maxOccurs="1" name="HEADER">
<xs:element minOccurs="1" maxOccurs="unbounded" name="Record">
<xs:element minOccurs="1" maxOccurs="1" name="FOOTER">
when a file (with a header 2 records and footer)is parsed through this schema. the parser recognizes recognizes the header and both the records and gives an exception after recognizing the 2nd record and doesn't give the footer. How do we define max and min occurs when there are 2 or more elements and middle element has unbounded as max occurs
EDIT:
thanks for the replies. This is my xsd file.
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:NS="sample.xsd" xmlns="sample.xsd" elementFormDefault="qualified" targetNamespace="sample.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="PTRO">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="HEADER">
<xs:complexType>
<xs:sequence>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="header_sub_element">
<xs:simpleType>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="1" maxOccurs="unbounded" name="Record">
<xs:complexType>
<xs:sequence>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Record_sub_element">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="11" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="1" maxOccurs="1" name="FOOTER">
<xs:complexType>
<xs:sequence>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="footer_sub_element">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="9" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
# marc_s the problem is when an input file (.txt file) which contains a header, 2 records, footer is parsed using this schema, the parser recognizes header and records...and after this it gives an exception since it doesn't recognize the footer. The max occurs of Record is unbounded. Does this have something to do with the exception ??
You have to use < sequence >< /sequence > instead of the < all >< /all > or < choice >< /choice >.
That should solve the problem.

How make univoque my enumeration by xs:unique

Can anyone point me as to why the unique element in my XSD is not forcing unique-ness? This should throw an error because the last ScreenResult element does not contain a unique value for the Type attribute. I should also note that I'm truly after forcing one of each Type within ScreenResults (ScreenResult is required to exist 3 times, there are 3 types of screens and I am requiring unique-ness) so if there is a better way to accomplish that, I'm all for that as well.
Thank you.
Here is my XML snippet:
<ScreenResults>
<ScreenResult Type="Screen Type A">1</ScreenResult>
<ScreenResult Type="Screen Type B">1</ScreenResult>
<ScreenResult Type="Screen Type B">2</ScreenResult>
</ScreenResults>
Here is my XSD snippet (also note that my original XSD snippets span multiple files but I have verified all of my namespaces are correct):
<xs:element name="ScreenResults" type="import:ScreenResults" minOccurs="0" maxOccurs="1">
<xs:unique name="UniqueScreenResults">
<xs:selector xpath="ScreenResult" />
<xs:field xpath="#Type" />
</xs:unique>
</xs:element>
<!--============ ScreenResults =============-->
<xs:complexType name="ScreenResults">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="ScreenResult" minOccurs="3" maxOccurs="3">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="enum:ScreenResult">
<xs:attribute name="Type" type="enum:ScreenType" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<!--============= ScreenType =============-->
<xs:simpleType name="ScreenType">
<xs:restriction base='xs:token'>
<xs:enumeration value='Screen Type A' >
<xs:annotation>
<xs:documentation>1</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='Screen Type B' >
<xs:annotation>
<xs:documentation>2</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='Screen Type C' >
<xs:annotation>
<xs:documentation>3</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<!--============ ScreenResult ============-->
<xs:simpleType name="ScreenResult">
<xs:restriction base='xs:token'>
<xs:enumeration value='1' >
<xs:annotation>
<xs:documentation>Positive</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='2' >
<xs:annotation>
<xs:documentation>Negative</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='3' >
<xs:annotation>
<xs:documentation>Not administered</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
I'm posting my solution for anyone else who runs into this problem.
Although I had asserted that all of my namespaces were correct, that was, of course the problem. All of the namespaces were correct except on the unique element itself.
I erroneously assumed that the unique element would not need to prefix a namespace as it was within the context. But that is not the case. Since I did declare a default namespace for the file, I still needed the prefix.
So my only change, and the solution, is as follows:
<xs:element name="ScreenResults" type="import:ScreenResults" minOccurs="0" maxOccurs="1">
<xs:unique name="UniqueScreenResults">
<xs:selector xpath="import:ScreenResult" />
<xs:field xpath="#Type" />
</xs:unique>
</xs:element>

Resources