Search code examples
xmlvalidationxpathschematron

Schematron & Xpath, testing for valid set of sub-elements and attributes


Since XSD doesn't cover my needs, i'm now evaluating Schematron. testing for other than allowed elements seems impossible. I need to validate elements where @type="colorSet".. Next tests are most important for me:

any other than this set of attributes and

any other than this set of optional elements

secondly how to check if values are alphanumerical or digits

Fyi, the valid XML options are;

<defaultBgColor type="colorSet" r="255" g="255" b="255"/>
<defaultBgColor type="colorSet" r="255" g="255" b="255" a="100"/>
<paint type="colorSet">
  <index>140</index>
</paint>
<paint type="colorSet">
  <name>blue</name>
</paint>

I want to test;

  • 'R','G','B' must be present
  • 'A' is optional , any other attribute not allowed
  • only 'index' or 'name' sub-elements allowed

This is the experpt of where i'm stuck;

    <!-- Don't know how to do the second assert? -->
    <rule context="//*[@type='colorSet' and count(child::*) = 0]">
      <assert test="@r and @g and @b"           >One of R G B missing</assert>
      <assert test="any other than @r,@g,@b,@a" >Invalid attribute   </assert>
    </rule>

    <!-- is a test like isNumber possible? -->
    <assert test="isNumber( text() )">Index is not a number</assert>

    <!-- is a test like isAlpha possible? -->
    <assert test="isAlpha( substring(text(),1) )">Invalid name</assert>

    <!-- How to assert "any other than valid (optional) elements" -->

Any comment or hint is welcome!


Solution

  • I think you need:

    <assert test="count(@*) > count(@r|@g|@b|@a)" >Invalid attribute   </assert> 
    
    <assert test="number(.) = number(.)">Index is not a number</assert> 
    
    <!-- It depends on what you mean: "does it start with no digit" -->
    <assert test="not(contains('0123456789',substring(.,1,1)))"
           >Invalid name</assert>