嵌入RelaxNG中的Schematron断言规则会产生未声明的名称空间前缀错误 示例代码我想做什么?我尝试了什么...

问题描述

示例代码

考虑以下一些人为设计的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

我想做什么?

我试图避免硬编码Schematron规则中当前定义的XPath Cell函数count元素的数量。即该部分(下面再次显示指出Cell元素的数量必须为六个:

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

我想做的是通过将与Cell元素相关联的aid:trowsaid:tcols属性的值相乘来推断table元素的数量。即从下面再次显示 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 Editor)

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关联的aid:trowsaid:tcol属性中省略了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>
    ...
    

解决方法

以下是一些选择:

    必须使用Schematron body元素声明在Schemetron中的断言测试中使用的
  1. 命名空间前缀。将以下内容添加为RelaxNG模式中WKScriptMessage中的第一个子代:

    func userContentController(_ userContentController: WKUserContentController,didReceive message: WKScriptMessage) { let dictionary = message.body as? [String: Any] guard let orderId = dictionary?["orderId"] as? Int,let email = dictionary?["email"] as? String,let status = dictionary?["status"] as? String else { return } delegate?.preScreenerFinished(orderId,email,status) }

  2. 或者,您可以使用xPath ns函数在assert测试中声明属性的名称空间。更改:

    <grammar>

    收件人:

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

    (与namespace-uri()相同)。

  3. 或者,如果您很懒,可以使用@aid:trows,它将选择任何命名空间的@*:trows[namespace-uri() = 'http://ns.adobe.com/AdobeInDesign/4.0/']属性。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...