xpath - 具有分层匹配的XPath

标签 xpath

**为澄清而编辑**

我继承了一堆类似于以下结构的XML文档(配置文件)(为了简洁起见,元素名称更改并简化了结构)。

<containers>
    <container id="c1">
        <ports>
            <port id="p2"/>
        </ports>
        <rules>
            <!--
              Within a container, a rule must refer to a port
              declared within the same container.
              A rule cannot refer to a port that does not
              exist in the enclosing container.
            -->
            <rule id="r1" portId="p1"/><!-- p1 is not in c1, but in c2, bad -->
            <rule id="r2" portId="p2"/><!-- this is good -->
            <rule id="r3" portId="p3"/><!-- p3 is nowhere, bad -->
        </rules>
    </container>
    <container id="c2">
        <ports>
            <port id="p1"/>
            <port id="p2"/>
        </ports>
        <rules>
            <rule id="r1" portId="p1"/>
        </rules>
    </container>
</containers>


容器可以具有点和规则(点和规则ID可以在容器之间重复;它们只需要在容器内唯一)。

要求是,如果规则引用了点ID,则必须在封闭容器中定义该点ID。

我需要在容器内搜索错误地引用不存在的点的规则。

我有xpath表达式,可以找到指向不存在点的规则(不幸的是对于整个xml文档。)

//*/rule/@portId[not( . =  //*/port/@id)]


该规则适用于整个文档,不包含在容器中。

也就是说,此xpath表达式将检测到容器c1中的规则r3引用了在文档中任何地方都不存在的端口p3。

但是,此相同的xpath表达式不会检测到容器c1中的规则r1引用的端口p2不在容器c1中。为什么?因为此xpath表达式将与容器c2中的端口p2匹配。

我的xpath表达式无法检测到这一点。

当然,我可以使用几个xpath表达式和它们之间的粘合代码来做到这一点(例如,通过将xpath表达式应用于每个容器),但是我希望是否有可能使用一个从根元素开始的单个xpath表达式。

有什么建议吗?

最佳答案

使用ancestor::轴的另一种选择...

//rule[not(@portId = ancestor::container//port/@id)]

关于xpath - 具有分层匹配的XPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45803701/

相关文章:

xml - XSLT:如何只输出本地化数据?

xml - 如何将 xslt 中的参数用作 XPath?

ruby, libxml 获取匹配 xpath 的子节点

xslt - XSLT 2.0:在文档树中将祖先轴限制为某个元素级别

php - 使用 PHP、Xpath 和/或 DOM 更改 HTML 内容

c++ - 具有 XPath 和宽字符支持的最轻量级 XML 解析器

xslt - 从属性值中去除前缀

php - PHP 中的 XPath 删除 HTML 标签

sql - 使用 SQL 解析 XML

xml - 在 XPATH 中使用多个命名空间