Xpath查询以根据条件选择忽略后代的所有元素

时间:2012-02-25 00:54:03

标签: xpath

我正在尝试选择所有<set>erase</set>元素,以便两个或多个元素在层次结构中具有<set>erase</set>时(例如:<b><d>都有{{} 1}})然后只需要选择父节点名中的元素(在这种情况下为<set>erase</set>)。

以下示例xml:

<b>

当我使用<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <a> <b> <set>erase</set> <d> <set>erase</set> </d> </b> <c> <x></x> </c> <e> <y> <set>erase</set> <q></q> </y> <z> <p> <set>erase</set> </p> </z> </e> </a> 时,我在结果集中获得了所有query = //set[contains(.,'erase')] nodesList <set>erase</set>

我需要帮助构建查询以选择b,d,y,p<set>erase</set>b的{​​{1}}。

1 个答案:

答案 0 :(得分:2)

以下是相同的解决方案

一个精确选择所需元素的XPath表达式是

          //*[set[. = 'erase' and not(node()[2])]
             and
              not(ancestor::*
                     [set
                        [. = 'erase' and not(node()[2])]
                     ]
                  )
              ]

基于XSLT的验证

<xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:output omit-xml-declaration="yes" indent="yes"/>
         <xsl:strip-space elements="*"/>

         <xsl:template match="/">
             <xsl:for-each select=
             "//*[set[. = 'erase' and not(node()[2])]
                 and
                  not(ancestor::*
                         [set
                            [. = 'erase' and not(node()[2])]
                         ]
                      )
                  ]">

              <xsl:value-of select="name()"/>
              <xsl:text>&#xA;</xsl:text>
            </xsl:for-each>
         </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<a>
    <b>
        <set>erase</set>
        <d>
            <set>erase</set>
        </d>
    </b>
    <c>
        <x></x>
    </c>
    <e>
        <y>
            <set>erase</set>
            <q></q>
        </y>
        <z>
            <p>
                <set>erase</set>
            </p>
        </z>
    </e>
</a>

评估包含的XPath表达式并输出所选元素的名称 - 正确且符合预期

b
y
p

如果您需要选择上面所选元素的set子元素,只需将上面的XPath表达式附加/set

          //*[set[. = 'erase' and not(node()[2])]
             and
              not(ancestor::*
                     [set
                        [. = 'erase' and not(node()[2])]
                     ]
                  )
              ]
               /set

再次,基于XSLT的验证

<xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:output omit-xml-declaration="yes" indent="yes"/>
         <xsl:strip-space elements="*"/>

         <xsl:template match="/">
             <xsl:copy-of select=
             "//*[set[. = 'erase' and not(node()[2])]
                 and
                  not(ancestor::*
                         [set
                            [. = 'erase' and not(node()[2])]
                         ]
                      )
                  ]
                   /set
                  "/>
         </xsl:template>
</xsl:stylesheet>

此转换仅评估上述XPath表达式,并将正确选择的三个set元素复制到输出中:

<set>erase</set>
<set>erase</set>
<set>erase</set>