How to validate XML elements with XSD schema?

1.8k views Asked by At

I would like to use conditions in my XSD schema for my XML document.

I used restrictions but it's not quite powerful.

Here is an example of what I did so far:

<xs:element name="Matricule">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="valeur">
                    <xs:simpleType>
                        <xs:restriction base="xs:integer">
                            <xs:minInclusive value="0"></xs:minInclusive>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
                <xs:element type="xs:string" name="backgroundcolor"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>

This example works fine but I check just if the value is greater than 0. But I would like to verify if the value is an Integer AND if the value is empty.

Maybe something like that:

If (value > 0 AND value < 100 AND value = '')

I found on Google a subject who calls about assertion, so I read the document and I did that

<xs:element name="Matricule">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="valeur">
                    <xs:simpleType>
                        <xs:restriction base="xs:integer">
                            <xs:minInclusive value="0"></xs:minInclusive>
                            **<xs:assertion test="($value mod 10) = 0"/>**
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
                <xs:element type="xs:string" name="backgroundcolor"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>

But it doesn't work, I always have an error.

Exemple 1 with value :

<racine>
  <row>
    <Matricule>
      <valeur>55</valeur>
      <backgroundcolor></backgroundcolor>
    </Matricule>
  </row>
</racine> 

Exemple 2 without value :

<racine>
  <row>
    <Matricule>
      <valeur></valeur>
      <backgroundcolor></backgroundcolor>
    </Matricule>
  </row>
</racine>

These two examples need to be correct but this one no :

<racine>
  <row>
    <Matricule>
      <valeur>gfd</valeur>
      <backgroundcolor></backgroundcolor>
    </Matricule>
  </row>
</racine>
2

There are 2 answers

4
Michael Kay On

I suspect you mean that the value must EITHER be a number between 0 and 100, OR be an empty string. If that's the case, you're getting muddled between AND and OR.

An empty string is not a valid instance of xs:integer, so you can't define this type as a restriction of xs:integer (because a restriction can only define a value space that is a subset of the base value space).

There are two common ways to define a simple type where the value must either be an X, or be empty:

  1. Define a union type whose member types are X, and a type derived from xs:string whose only permitted value is ""

  2. Define a list type whose item type is X, and whose maxOccurs is 1.

(In this case X is a restriction of xs:integer with minInclusive=0, maxInclusive=100).

Personally I prefer (2): it works better if you are using schema-aware queries and transformations. But if you're only using the schema for validation, it makes no difference.

6
kumesana On

If you need to accept empty elements, then their content is not of type integer, as an empty string does not represent a number.

You will have to settle on type xs:string and just restrict it with a pattern that accept either integers or empty string.

This would work:

<xs:simpleType>
  <xs:restriction base="xs:string">
    <xs:pattern value="[0-9]*"/>
  </xs:restriction>
</xs:simpleType>

As it says you accept, a digit from 0 to 9, zero or more consecutive times.

If you need it also inferior to 100, I'll let you find a pattern that enforces this additional condition.