问题描述
示例代码
考虑以下一些人为设计的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>
此规则assert
是Cell
元素节点的数量必须等于6
:
我想做什么?
我试图避免硬编码Schematron规则中当前定义的XPath Cell
函数中count
元素的数量。即该部分(下面再次显示)指出Cell
元素的数量必须为六个:
<sch:assert test="count(./Cell) = 6">...</sch:assert>
^
我想做的是通过将与Cell
元素相关联的aid:trows
和aid: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
命名空间前缀相关,我尝试了以下方法,这些方法可以成功工作:
-
在 file.xml 中,我从与
aid
关联的aid:trows
和aid:tcol
属性中省略了table
前缀,如下所示下方:... <table trows="3" tcols="2"> ... </table>
-
然后重新定义:
基本上,我将
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
-
命名空间前缀。将以下内容添加为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) }
-
或者,您可以使用xPath
ns
函数在assert测试中声明属性的名称空间。更改:<grammar>
收件人:
<sch:ns prefix="aid" uri="http://ns.adobe.com/AdobeInDesign/4.0/"/>
(与
namespace-uri()
相同)。 -
或者,如果您很懒,可以使用
@aid:trows
,它将选择任何命名空间的@*:trows[namespace-uri() = 'http://ns.adobe.com/AdobeInDesign/4.0/']
属性。
body
元素声明在Schemetron中的断言测试中使用的