Recursion 在一组循环有序元素中表示递归引用
我正在尝试编写一个具有以下规则的RelaxNG模式:Recursion 在一组循环有序元素中表示递归引用,recursion,relaxng,relaxng-compact,Recursion,Relaxng,Relaxng Compact,我正在尝试编写一个具有以下规则的RelaxNG模式: 行元素可以包含零个或多个A和b元素 每个a元素必须有相应的b元素和 反之亦然 a元素必须始终在其匹配的b元素之前 因此,以下各项均应视为有效: <line><a/><b/></line> <line><a/><a/><b/><b/></line> <line><a/><a/><b
行
元素可以包含零个或多个A
和b
元素a
元素必须有相应的b
元素和
反之亦然a
元素必须始终在其匹配的b
元素之前<line><a/><b/></line>
<line><a/><a/><b/><b/></line>
<line><a/><a/><b/><a/><b/><b/></line>
然而,Jing认为这是“对‘pair’的错误递归引用”。我一辈子都想不出怎么解决这个问题!有什么想法吗?RELAXNG的模式(如DTD和XSD的内容模型)本质上是正则表达式;它们在元素名和文本集上定义正则语言。您要查找的a/b匹配需要上下文无关语法;因此,不能在Relax NG中定义它
当然,它可以是近似的。如果您期望在实践中,您的a/b对不会超过五对(或者更准确地说:您从未见过匹配的b
元素的a
元素不会超过五对),您可以定义以下任一语言
第一:
pair0 = (a, b)*
pair1 = (a, pair0, b)*
pair2 = (a, pair1, b)*
pair3 = (a, pair2, b)*
pair4 = (a, pair3, b)*
pair5 = (a, pair4, b)*
pair6 = (a, pair5, b)*
pair7 = (a, pair6, b)*
pair8 = (a, pair7, b)*
pair9 = (a, pair8, b)*
pair = (a, pair9, b)*
这定义了严格执行两个规则但不能处理嵌套深度超过10的a/b对的语言子集。(或11,取决于您正在计算的内容。)此定义接受的每个文档都将是您实际需要的语言的成员,但并非该语言的每个成员都将被接受
如果拒绝该语言的有效实例是不可接受的,则可以如上所述定义模式,但将pair0重新定义为:
pair0 = (a, (a|b)*, b)*
这定义了语言的一个超集,在该超集中,a/b对的规则被强制执行到嵌套的最大级别,但在该超集中,一旦嵌套级别超过该最大级别,则放弃规则。在这种情况下,所需语言的每个成员都会被接受,但一些不应该被接受的垃圾也会被接受
这些近似值在您的应用程序中是否有用,我留给您来决定
如果近似值不可接受,您可能会发现通过不同的XML定义更容易获得所需的内容
一个简单的改变是将每个匹配的a
和b
封装在一个元素中(我称之为e
):
现在,文档的有效性提供了一个非常简单的保证,即a
元素和b
元素按要求配对,并且每个a
都在其匹配b
之前
假设a
和b
为空,每个a
紧跟e
的开始标记,每个b
紧跟同一e
元素的结束标记,您可以将a
和b
元素分别完全替换为e
的开始标记和e
的结束标记,并将行声明为
element line { e* }
e = element e { e* }
SAX接口、DOM接口、XSLT、XQuery以及我所知道的所有其他处理XML的方法使将操作与元素的开始和结束相关联变得简单,就像将操作与空元素相关联一样
您的有效示例将变成:
<line><e></e></line>
<line><e><e></e></e></line>
<line><e><e></e><e></e></e></line>
您的无效示例将变成非格式良好的数据
element line { pair* }
a = element a { empty }
b = element b { empty }
pair = element e { a, pair*, b }
element line { e* }
e = element e { e* }
<line><e></e></line>
<line><e><e></e></e></line>
<line><e><e></e><e></e></e></line>