xmlxsdxml-validationschematron

Schematron rule fails Pattern '' Failed : [123] Picture obligatory


I am using schematron validation for XML files. I try to write my first rule and I check it with online tool https://www.liquid-technologies.com/online-schematron-validator. What is wrong with this rule ? What I want to do is to validate that Picture node is present and also if it is present, whether it has some text inside, so it cannot be like this: <Picture/> but rather <Picture>aasd</Picture>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message>
  <book>
    <chapterA>
      <SectionA>
        <Picture>picture</Picture>
      </SectionA>
    </chapterA>
  </book>
</Message>

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
  <title>Myrule</title>
  <pattern>
    <rule context="Message">
      <assert test="boolean(/*[local-name() = 'book']/*[local-name() = 'chapterA']/*[local-name() = 'SectionA']/*[local-name() = 'Picture'])" flag="fatal" id="id123">[123] Picture obligatory</assert>
    </rule>
  </pattern>
</schema>

Solution

  • I have no idea what schematron is but looking at the rule i think that the xpath is incorrect. If you change

    <assert test="boolean(/*[local-name() = 'book']/*[local-name() = 'chapterA']/*[local-name() = 'SectionA']/*[local-name() = 'Picture'])" flag="fatal" id="id123">[123] Picture obligatory</assert>
    

    to

    <assert test="boolean(/Message/*[local-name() = 'book']/*[local-name() = 'chapterA']/*[local-name() = 'SectionA']/*[local-name() = 'Picture'])" flag="fatal" id="id123">[123] Picture obligatory</assert>
    

    it works.

    but your xpath does not check if the picture element is empty or not. I also think it can be simplified to this

    <assert test="boolean(/Message/book/chapterA/SectionA/Picture/text())" flag="fatal" id="id123">[123] Picture obligatory</assert>
    

    this will throw your defined fatal when the picture element is empty.