RelaxNG 中嵌入的 Schematron 断言规则产生未声明的命名空间前缀错误

Schematron Assert rule embedded in RelaxNG produces undeclared namespace prefix error

示例代码

考虑以下有点做作的 XML 实例:

file.xml

<?xml version="1.0" encoding="UTF-8"?>
<section xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/">
  <table aid:trows="3" aid:tcols="2">
    <Cell>header column 1</Cell>
    <Cell>header column 2</Cell>
    <Cell>row 1 column 1</Cell>
    <Cell>row 1 column 2</Cell>
    <Cell>row 2 column 1</Cell>
    <Cell>row 2 column 2</Cell>
  </table>
</section>

它使用以下 Relax NG 模式成功验证:

schema.rng

<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
  datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
  xmlns:sch="http://purl.oclc.org/dsdl/schematron"
  xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/"
  xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/">
  <start>
    <ref name="section"/>
  </start>
  <define name="section">
    <element name="section">
      <ref name="table"/>
    </element>
  </define>
  <define name="table">
    <sch:pattern name="Test attributes aid:rows and aid:tcols when multiplied equal count of Cell elements">
      <sch:rule context="table">
        <sch:assert test="count(./Cell) = 6">Count of Cell elements does not match specified @aid:rows and @aid:tcols.</sch:assert>
      </sch:rule>
    </sch:pattern>
    <element name="table">
      <attribute name="aid:trows">
        <data type="integer"/>
      </attribute>
      <attribute name="aid:tcols">
        <data type="integer"/>
      </attribute>
      <oneOrMore>
        <element name="Cell">
          <text/>
        </element>
      </oneOrMore>
    </element>
  </define>
</grammar>

注:schema.rng中的内嵌Schematron规则,即如下部分:

<sch:pattern name="Test attributes aid:rows and aid:tcols when multiplied equal count of Cell elements">
 <sch:rule context="table">
   <sch:assert test="count(./Cell) = 6">Count of Cell elements does not match specified @aid:rows and @aid:tcols.</sch:assert>
 </sch:rule>
</sch:pattern>

这条规则assertCell个元素节点的数量必须等于6:

我想做什么?

我试图避免硬编码 Cell 元素的计数必须在当前在 Schematron 规则中定义的 XPath count 函数中。即这部分 (在下面再次显示) 说明 Cell 元素的数量必须是六个:

<sch:assert test="count(./Cell) = 6">...</sch:assert>
                                  ^

我想做的是通过乘以与 table 关联的 aid:trowsaid:tcols 属性的值来推断 Cell 元素的计数必须是多少元素。即从下面再次显示的 file.xml 中的这些属性推断它:

<table aid:trows="3" aid:tcols="2">
                  ^             ^
  ...
</table>

我尝试了什么...

我尝试重新定义 Schematron 规则中的 XPath count 函数,如下所示。

<sch:assert test="count(./Cell) = @aid:trows * @aid:tcols">...</sch:assert>

但是,尝试验证 file.xml 会产生以下错误 (顺便说一句。我正在使用 Oxygen XML 编辑器):

Failed to compile stylesheet. 1 error detected.
Undeclared namespace prefix {aid}
Got a fatal error trying to create a transformer from the stylesheet!

aid 命名空间前缀似乎有问题!

我在这里误解了什么?我该如何解决这个问题?

什么有效?

为了确定它是否与 aid 命名空间前缀相关,我尝试了以下确实有效的方法:

  1. file.xml中我省略了关联的aid:trowsaid:tcol属性中的aid前缀table 如下所示:

    ...
    <table trows="3" tcols="2">
        ...
    </table>
    
  2. 然后重新定义:

    • Schematron 规则中的 XPath count 函数为 count(./Cell) = @trows * @tcols
    • 并将 table 的属性定义为 trowstcols,即省略了 aid: 前缀。

    基本上我将 table 的命名模式重新定义为以下内容:

    ...
    <define name="table">
      <sch:pattern name="Test attributes aid:rows and aid:tcols when multiplied equal count of Cell elements">
        <sch:rule context="table">
          <!-- change below -->
          <sch:assert test="count(./Cell) = @trows * @tcols">Count of Cell elements does not match specified @aid:rows and @aid:tcols.</sch:assert>
        </sch:rule>
      </sch:pattern>
      <element name="table">
        <!-- change below -->
        <attribute name="trows">
          <data type="integer"/>
        </attribute>
        <!-- change below -->
        <attribute name="tcols">
          <data type="integer"/>
        </attribute>
        <oneOrMore>
          <element name="Cell">
            <text/>
          </element>
        </oneOrMore>
      </element>
    </define>
    ...
    

这里有一些选项:

  1. Schemetron 断言测试中使用的名称空间前缀必须使用 Schematron ns 元素声明。添加以下内容作为 RelaxNG 架构中 <grammar> 中的第一个子项:

    <sch:ns prefix="aid" uri="http://ns.adobe.com/AdobeInDesign/4.0/"/>

  2. 或者,您可以使用 xPath namespace-uri() 函数在断言测试中断言属性的名称空间。变化:

    @aid:trows

    至:

    @*:trows[namespace-uri() = 'http://ns.adobe.com/AdobeInDesign/4.0/']

    tcols 也一样)。

  3. 或者,如果你很懒,你可以使用 @*:trows,这将 select trows 任何命名空间的属性。