Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restricting specific numbers in XSD

Tags:

xml

xsd

xsd-1.1

I'm trying to create an XSD which is supposed to validate the integer value of an XML element. What I want to achieve is to be able to limit this value to both multiple ranges (so min/maxInclusive won't do), and some specific values.

Let's give an example. I want the element to be valid, if it contains a 1, a number between 9 and 12, or a number between 15 and 20. I tried to come up with a pattern

<xs:pattern value="[(1)(9-12)(15-20)]"/>

but that doesn't work, because (as I understand it) the 9-12 part does something like 9|0|1...., because it interprets the 12 not as a whole. With single-digit numbers like

<xs:pattern value="[(1)(3-5)(7-9)]"/>

it does work. I tried to enclose the multidigit numbers in more parentheses like 9-(12), but to no avail.

I could try to use enumerations for this in a way like this:

<xs:restriction base="xs:integer">
    <xs:enumeration value="1"/>
    <xs:enumeration value="9"/>
    <xs:enumeration value="10"/>
    <xs:enumeration value="11"/>
    <xs:enumeration value="12"/>
....
</xs:restriction>

, but that's incredibly impractical, especially for large ranges. The same goes for the same thing in pattern form:

<xs:pattern value="1|9|10|11|12|15....."/>

So I see two paths right now: either there is a pattern, that I'm not able to come up with by myself, which allows me to use multiple single numbers and ranges including multidigit numbers, or there is a way to somehow do something like

<xs:enumeration value="9"-"12"/>

It seems to be pretty hard to create such a regex generically, as far as I can tell from what my colleagues with more experience with regexes say. Coming up with localized solutions for my exact example here isn't too hard, but I'm looking for a generic solution, with which it is easy to just get an arbitrary list like (1,3-5,9-12,99-999) and make an XSD restriction out of it without too much hassle.

From what I see, the enumeration approach with splitting the ranges into all the numbers contained seems to be the most likely approach to be actually possible, but it would still be incredibly ugly.

This is about XSD 1.1. Maybe there is a completely different approach that I have not stumbled upon yet?

EDIT: Even though I just self-answered, I will leave the question open for today, in case someone can come up with something more elegant than the...thing I created. (I'm not sure about deleting the question - if you think this is not helpful, please flag it or something like that. Thank you.)

like image 845
LindenRathan Avatar asked Mar 16 '23 02:03

LindenRathan


1 Answers

Self-answer:

Think the whole morning about it and you have no idea, post the question and your brain immediately comes up with a solution afterwards...

It didn't occur to me that it is possible to actually use multiple min/maxInclusives, because I thought from the names and such that they would be pretty much unique. Well, that's not the case, so I came up with this beautiful abomination:

<xs:simpleType name="RANGETEST_Data">
  <xs:union>
     <xs:simpleType>
        <xs:restriction base="xs:integer">
           <xs:minInclusive value="9"/>
           <xs:maxInclusive value="12"/>
        </xs:restriction>
     </xs:simpleType>
     <xs:simpleType>
        <xs:restriction base="xs:integer">
           <xs:minInclusive value="15"/>
           <xs:maxInclusive value="20"/>
        </xs:restriction>
     </xs:simpleType>
     <xs:simpleType>
        <xs:restriction base="xs:integer">
            <xs:enumeration value="1"/>
        </xs:restriction>
     </xs:simpleType>
  </xs:union>
</xs:simpleType>

Which is exactly the type of generic approach I wanted.

like image 135
LindenRathan Avatar answered Mar 23 '23 19:03

LindenRathan