1

我遇到了一个有趣的需求,我已经有自己的工作实现,但我正在努力确保我已经涵盖了所有极端情况。

我想要实现的最好描述为“XPath 条件委托”。

假设某种晦涩的模式语言可以使用任意 XPath 条件来约束实例元素。这些条件被转换为 Schematron 断言,然后应用于 XML 实例文档。为了使其工作,每个条件都需要一个上下文节点来测试表达式(这就像说:“在 XML 实例文档中找到某个元素,然后检查 XPath 条件是否适用于它”)。事情是; 可以为虚拟/抽象节点定义我的模式语言中的某些条件,这些节点从未出现在实例文档中(xsd:choice 在这里可能是一个合适的类比——它只存在于语言文件中,而不存在于实例中)。所以我想,好吧,让我们简单地将条件从父虚拟节点委托给子节点,实际出现在 XML 实例中。结果很好!如果您只使用绝对 XPath 位置路径,那就是......

模式语言的假设示例:

element smth {
    element c-enabled;
    choice c {
        assert "c-enabled = 'true'"; <!-- context node is <smth>, first instatiable ancestor -->
        element one;
        element two;
    }
    element foo;
}

这基本上是说,允许<smth>具有 a<c-enabled>和一个<foo>子元素的元素,并且 if<c-enabled>的值'true'也允许 a<one>或一个<two>子元素。有效实例文档的示例:

<smth>
    <c-enabled>true</c-enabled>
    <two/>
    <foo/>
</smth>

因此,如前所述,我决定将条件委托给<one>and <two>,实质上是在运行时将上述模式重构为以下内容:

element smth {
    element c-enabled;
    choice c {            
        element one {
            assert "c-enabled = 'true'"; <!-- context node is <one>, never satisfied since <one> has no <c-enabled> child -->
        }
        element two {
            assert "c-enabled = 'true'"; <!-- context node is <two>, never satisfied since <two> has no <c-enabled> child -->
        }
    }
    element foo;
}

这显然只有在使用绝对路径编写 XPath 条件时才有效。每次在实例文档中遇到<one>or<two>时,都会通过将它们用作初始上下文节点来检查条件(它们是current()XSLT 中返回的内容)。

因此,在阅读了一些XPath 规范并使用结合此语法的精彩ANTLR4 工具创建 XPath 解析器并实现了转换解析树步行器之后,我现在将原始模式重构为:

element smth {
    element c-enabled;
    choice c {            
        element one {
            assert "../c-enabled = 'true'"; <!-- u-huh, this is what we're after -->
        }
        element two {
            assert "../c-enabled = 'true'"; <!-- u-huh, this is what we're after -->
        }
    }
    element foo;
}

请注意,这只是我正在处理的 XPath 条件的一个简单示例(这不是简单地编写正则表达式来处理它的问题),因为它们是完全任意的,由创建模式定义的人组成。关于它们,我唯一可以确定的是它们是有效的 XPath 1.0 表达式(只有基本函数,没有变量)。


所以我的问题是:根据 XPath 1.0 规范,XPath 表达式中可能出现引用初始上下文节点(以相对方式)的构造的位置是什么?

我目前的假设是:任何在解析树中没有以下祖先的RelativeLocationPath : AbsoluteLocationPathPredicate。如果 RelativeLocationPath 前面有一个 AbsoluteLocationPath,则该组合形成一个绝对构造。在谓词中,所有路径都指向不同的上下文节点或者是绝对的。

我假设这是基于我制作的这张图(表示使用我上面提到的语法解析 XPath 时如何调用产品): 语法图


下面是一些我需要在 XPath 表达式中找到的地方的示例。基本上是在寻找这些(可能还有其他)的正式定义。

(../area-type = 'stub') or (../area-type = 'nssa')
 ^                          ^
(../../../cacheMode != 'ipfix:immediate')
 ^
address-family='ipV4' and safi='nlri-unicast'
^                         ^
(../../../cacheMode != 'ipfix:immediate') and ((count(../ieEnterpriseNumber) = 0) or (../ieEnterpriseNumber != 29305))
 ^                                                    ^                               ^

4

1 回答 1

1

初读时您的分析听起来似乎是合理的,但是由于您正在寻找极端案例,因此很大程度上取决于您的意思。如果您的意思是“在语法中, . 和 .. 指的是初始上下文项,而不是以其他方式设置的上下文项”,那么(假设“以其他方式设置”在某些情况下被定义和理解合适的方式)你的描述似乎是正确的。但这些并不是唯一的地方。和 .. 可能指的是初始上下文项或其父项:考虑./.-- 两个点都指同一个节点,即初始上下文项。或者./*/../.——等等。

如果我正确理解您的想法,您希望接受与特定节点关联的 XPath 表达式,但不是将该节点作为当前节点评估它们,而是希望将适当的表达式传递给其他节点以将这些节点作为上下文项进行评估.

如果您将自己限制为路径表达式,并且您的委托始终要么是抽象类的实例化,要么是子类的实例化,那么 (a) 绝对路径表达式和相对路径表达式之间的区别很容易识别,并且 (b) 必要的修改路径表达式很容易描述(不更改或在开头添加“../”)。如果你允许更通用的表达式——例如函数调用——你将不得不理解表达式结构和更复杂的调整。如果用户写入local-name() = 'barracuda'并且由于某种原因被委托给孩子,那么孩子需要评估local-name(..) = 'barracuda'。(在 XPath 2.0 中,我猜想在前面加上 ../ 会起作用,但我认为在 1.0 中不行。)

您还可以在有关 XPath 表达式的流式求值的文献中找到相关注意事项。

于 2013-08-16T02:18:44.960 回答