用于检查文件是否具有对应元素的 Schematron 规则

Schematron rule to check if files have corresponding elements

我有这样的文件结构:

bookmap.ditamap
├── en-US/
│   └── CTR_MyProduct.ditamap
├── es-ES/
│   └── CTR_MyProduct.ditamap
└── fr-FR/
    └── CTR_MyProduct.ditamap

bookmap.ditamap的内容是:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bookmap PUBLIC "-//OASIS//DTD DITA BookMap//EN" "bookmap.dtd">
<bookmap>
    <booktitle><mainbooktitle/></booktitle>
    <part>
        <mapref href="en-US/CTR_Product.ditamap"/>
    </part>
    <part>
        <mapref href="fr-FR/CTR_Product.ditamap"/>
    </part>
</bookmap>

我想要一个 Schematron 规则,它应该在子目录中爬行以查找以 CTR_ 开头并以 .ditamap 结尾的文件,它抱怨如果没有相应的 <part> 元素,例如:

<part>
  <mapref href="xx-YY/CTR_Product.ditamap"/>
</part>

在此示例中,西班牙语 (es-ES) 地图没有 <part> 元素。这应该报告。您认为这可以在 Schematron 中验证吗?

有了底层的 XSLT/XPath 3 支持和 Saxon 9 或 10 或 11,您可能可以做到,例如

every $uri in uri-collection('?select=CTR_Product.ditamap;recurse=yes') 
satisfies 
  some $part in part 
  satisfies contains($uri, $part/mapref/@href)

如果这些元素在命名空间中,您还需要将其设置为默认的 XPath 选择命名空间。

您也可以使用通配符,例如uri-collection('?select=CTR_*.ditamap;recurse=yes').

也许使用 ends-with($uri, $part/mapref/@href) 而不是 contains($uri, $part/mapref/@href) 是更好的检查方法。

在 Schematron 的上下文中更完整:

    <sch:rule context="bookmap">
        <sch:let name="parts" value="part"/>
        <sch:let name="uris" value="uri-collection('?select=*.ditamap;recurse=yes')"/>
        <sch:assert test="every $uri in $uris
            satisfies 
            some $part in part 
            satisfies ends-with($uri, $part/mapref/@href)">
            Not every URI exists. 
            <sch:value-of select="$uris[not(some $ref in $parts/mapref satisfies ends-with(., $ref/@href))]"/>
        </sch:assert>  
    </sch:rule>