首页 文章

带有层次匹配的XPath

提问于
浏览
1

编辑澄清

我继承了一堆类似于以下结构的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指的是不在容器c1中的端口p2 . 为什么?因为此xpath表达式将与容器c2中的端口p2匹配 .

My xpath expression would not detect this.

当然,我可以使用几个xpath表达式并在它们之间粘合代码(例如,通过将xpath表达式应用于每个容器)来执行此操作,但我希望是否可以使用从根元素开始的单个xpath表达式 .

有什么建议?

2 回答

  • 2

    使用 ancestor:: 轴的另一个选项......

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

    试试这个吧 .

    //rule[@portId[not(. =  ./parent::rule/parent::rules/parent::container/*/port/@id)]]
    

    这似乎对我有用 . 测试:

    <containers>
        <container id="c1">
            <ports>
                <port id="p2"/>
                <port id="p4"/>
            </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"/>
                <rule id="r2" portId="p4"/>
            </rules>
        </container>
    </containers>
    

    使用this online processor .

    得到以下输出

    Element='<rule id="r1" portId="p1"/>'
    Element='<rule id="r3" portId="p3"/>'
    Element='<rule id="r2" portId="p4"/>'
    

相关问题