0
votes

I have an XML document with a list of xml, pdf, and tif files. I need to test via Schematron that each xml has a matching pdf file, and vice versa.

My XML:

<folder>
    <files>
        <file>foo.xml</file>
        <file>foo.pdf</file>
        <file>bar.xml</file>
        <!-- Missing file <file>bar.pdf</file> -->
        <file>foo.tif</file>
    </files>
</folder>

My Schematron:

<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">

<!-- XML/PDF Matches -->

<pattern abstract="false" id="xmlPdfPair">
    <rule context="folder/files//file">
        <assert test="substring-before(.,'.xml') eq substring-before(.,'.pdf')">The XML or PDF (<value-of select="."/>) does not have a matching PDF or XML file.</assert>
    </rule>
</pattern>

I want the rule to fire on the missing bar.pdf which should be present in the file. My Schematron is not doing the trick. I feel like I need a for-each construct here. Would the use of keys make this simpler?

1

1 Answers

1
votes

Change it to mentioned to get your desired validation:

  <pattern abstract="false" id="xmlPdfPair">
    <rule context="//file[contains(text(),'.xml')]">
      <let name="fileName" value="substring-before(.,'.xml')"/>
      <assert test="(following-sibling::file)[1][text()=concat($fileName,'.pdf')]">The XML or PDF
          (<value-of select="."/>) does not have a matching PDF or XML file.</assert>
    </rule>
  </pattern>