Reputation: 25
I need to define an element with multiple patterns, like gDay
, gMonth
, gYear
, dateTime
, etc. How can I define a restriction in XSD to do that?
Someting like this:
<dates>
<out>2012</out>
</dates>
<xs:complexType name="infodates">
<xs:sequence>
<xs:element name="out" type="xs:dateTime"&"xs:gMonth"/>
</xs:sequence>
</xs:complexType>
Thanks
Upvotes: 1
Views: 3692
Reputation: 12187
Short answer: xml schema can't concatenate simple datatypes.
It might not be what you want anyway: xs:gMonth
requires a double-hyphen prefix (e.g. "--05"), and xs:gDay
needs a triple-hyphen (e.g. "---31"). Not what I expected!
Here's examples for each simple datatype. There's some combined types built-in too: gYearMonth
, gMonthDay
etc.
Along these lines, xs:dateTime
has a long definition: '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
Only three parts can be left out, so it needs yyyy-mm-ddThh:mm:ss
- your example in <out>2012</out>
isn't valid with respect to this.
Long answer: However, xml schema can combine simple datatypes by union
(like choice) and list
(space-separated list of the same type). So, you can do something like: (gDay|gMonth|gYear|dateTime)*
(not valid xsd syntax, just illustrative). This isn't ordered and allows duplicates, so e.g. "---31 --05 --05" is valid. Here it is in xsd syntax:
$ cat catDatatypes.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="eg" type="myString_Type"/>
<xs:simpleType name="myString_Type">
<xs:list>
<xs:simpleType>
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:gDay"/>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:gMonth"/>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:gYear"/>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:dateTime"/>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:list>
</xs:simpleType>
</xs:schema>
$ xmllint --schema catDatatypes.xsd catDatatypes.xml
<eg>2012 --12 ---01 --12 ---31 --05 --05</eg>
catDatatypes.xml validates
Conclusion: You can't reuse the built-in datatypes in the way you (and I) would like, and they don't seem very nice anyway. You're probably better off explicitly defining it yourself, as in InfantProgrammer'Aravind's answer. (Or, you could use separate attributes for each component instead - which would make it easier for whoever is parsing it, too).
For fun, I tried shortening InfantProgrammer'Aravind's answer (though it's arguable whether this makes it clearer...). It retains the check of 12-hour with am/pm vs. 24-hour without am/pm (but doesn't accept empty aka null value).
<xs:simpleType name="CRNDATETIME2">
<xs:restriction base="xs:string">
<xs:pattern value="(0[1-9]|1[012])/(0[1-9]|[12]\d|3[01])/([12]\d{3}) ((0\d|1[012])(:[0-5]\d){2}|(0\d|1[012])(:[0-5]\d){2} [aApP][mM])"/>
</xs:restriction>
</xs:simpleType>
Here's a brief guide to regex in XSD; here's a long one.
BTW: Turns out you can denote "[1-9]" as "[\d-[0]]", which is a "Character Class Subtraction", not a range.
Upvotes: 1
Reputation: 12154
This can be done having custom pattern as TYPE.. example:
<xs:simpleType name="CRNDATETIME">
<xs:restriction base="xs:string">
<xs:pattern value="|(((01|02|03|04|05|06|07|08|09|10|11|12)/(01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)/[1-2][0-9][0-9][0-9][ ](00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23)[:][0-5][0-9][:][0-5][0-9])|
((01|02|03|04|05|06|07|08|09|10|11|12)/(01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)/[1-2][0-9][0-9][0-9][ ](01|02|03|04|05|06|07|08|09|10|11|12)[:][0-5][0-9][:][0-5][0-9] [aApP][mM]))"/>
</xs:restriction>
</xs:simpleType>
this accepts datetime value of below patterns
1. MM/DD/YYYY hh:mm:ss aAmM/pPmM ..
2. MM/DD/YYYY HH:mm:ss
also accepts null value ..
I know it would be bit difficult rather very difficult.. but achievable ..
Upvotes: 1