Recursion 在一组循环有序元素中表示递归引用

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

我正在尝试编写一个具有以下规则的RelaxNG模式:

  • 元素可以包含零个或多个
    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>