用于查找无效记录的 SchemaTron 规则

SchemaTron rule to find invalid records

我正在尝试使用 Schematron 规则验证以下 XML。

XML:

<?xml version="1.0" encoding="utf-8"?>
<Biotic><Maul><Number>1</Number>
 <Record><Code IDREF="a1"/>
   <Detail><ItemID>1</ItemID></Detail>
   <Detail><ItemID>3</ItemID></Detail>
 </Record>
 <Record><Code IDREF="b1"/>
   <Detail><ItemID>3</ItemID></Detail>
   <Detail><ItemID>4</ItemID></Detail>
 </Record>
 <Record><Code IDREF="b1"/>
   <Detail><ItemID>4</ItemID></Detail>
   <Detail><ItemID>6</ItemID></Detail>
 </Record>
 <Record><Code IDREF="c1"/>
   <Detail><ItemID>5</ItemID></Detail>
   <Detail><ItemID>5</ItemID></Detail>
 </Record>
</Maul></Biotic>

并且检查是“ItemID 对于给定 Maul 中的给定代码应该是唯一的。”

因此根据要求,代码为 b1 的记录无效,因为 ItemId 4 存在于两条记录中。

同样,记录C1也是无效的,因为c1有两个itemId为5的节点。

记录a1有效,下一条记录中也有ItemID 3但编码不同

我试过的 Schematron 规则:

<?xml version="1.0" encoding="utf-8" ?><schema xmlns="http://purl.oclc.org/dsdl/schematron" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<title>Schematron validation rule</title>
<pattern id="P1">
  <rule context="Maul/Record" id="R1">
   <let name="a" value="//Detail/[./ItemID, ../Code/@IDREF]"/>
   <let name="b" value="current()/Detail/[./ItemID, ../Code/@IDREF]"/>
   <assert test="count($a[. = $b]) = count($b)">              
    ItemID should be unique for the given Code within the given Maul.
   </assert>
 </rule>
</pattern>
</schema>

这两个 let 值似乎有问题。他们将每个 return 一个 Detail 元素(及其所有内容,包括属性、子元素和文本节点)。我不确定谓词 [./ItemID, ../Code/@IDREF] 中的代码将要做什么,但我认为它将 return 具有子 ItemID 元素或子元素的所有 Detail 元素具有 @IDREF 属性的同级 Code 元素,无论 ItemID@IDREF 的值是什么。

我想我会将规则/@context 更改为 ItemID,因此对于违反约束的每个 ItemID,断言都会失败一次。

这里有一个规则并断言它可以正常工作:

<?xml version="1.0" encoding="utf-8" ?><schema xmlns="http://purl.oclc.org/dsdl/schematron" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<title>Schematron validation rule</title>
<pattern id="P1">
  <rule context="Maul/Record/Detail/ItemID" id="R1">
   <assert test="count(ancestor::Maul/Record[Code/@IDREF = current()/ancestor::Record/Code/@IDREF]/Detail/ItemID[. = current()]) = 1">
    ItemID should be unique for the given Code within the given Maul.
   </assert>
 </rule>
</pattern>
</schema>

assert 测试发现,在祖先 Maul 中,任何 RecordCode/@IDREF 等于 RecordCode/@IDREF当前 ItemID 在。至少,它会找到一个 Record(当前 ItemID 在的那个)。然后它会在那些 Record 中查找等于当前 ItemID 的任何 Detail/ItemID。它会找到至少一个(当前 ItemID)。 count 函数计算找到了多少 ItemID。如果找到多个,则断言失败。

感谢 https://www.liquid-technologies.com/online-schematron-validator 的参考!我不知道那个工具。