ciroid
ciroid

Reputation: 25

Use multiple patterns in an element XML

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

Answers (2)

13ren
13ren

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

Rookie Programmer Aravind
Rookie Programmer Aravind

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

Related Questions