使用:
.//element[(ancestor::main|ancestor::element)[last()][self::main]]
这是使用 XSLT 进行的简单验证:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:template match="/*">
  <xsl:for-each select=
   ".//element
       [(ancestor::main|ancestor::element)
                          [last()][self::main]
       ]">
   <xsl:copy-of select="."/>
==================
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<main>
    <sub1>
        <element>
            <sub2>
                <element>
                    <sub3/>
                </element>
            </sub2>
        </element>
    </sub1>
    <sub4>
        <sub5>
            <element>
                <sub6>
                    <element>
                        <sub7/>
                    </element>
                </sub6>
            </element>
        </sub5>
    </sub4>
    <sub8>
        <element/>
    </sub8>
</main>
Xpath 表达式在当前节点是文档中的顶部节点的情况下进行评估,然后使用方便注意的分隔符字符串将此评估的结果复制到输出:
<element>
   <sub2>
      <element>
         <sub3/>
      </element>
   </sub2>
</element>
==================
  <element>
   <sub6>
      <element>
         <sub7/>
      </element>
   </sub6>
</element>
==================
  <element/>
==================
说明:
表达方式:
    .//element
       [(ancestor::main|ancestor::element)
                                     [last()]
                                        [self::main]
       ]
element选择当前节点的所有后代元素,两个可能的祖先中的第一个(向上)main或者element是main。
也就是说,没有一个element是所选的祖先element并且在祖先之前发生(向上)main。
要理解为什么last()被用作谓词而不仅仅是[1],我们需要记住两个祖先中最近的一个是它们中的最后一个。
请注意:
这个 XPath 表达式正确地选择了所有想要element的元素,即使在当前节点本身有一个element祖先的情况下也是如此。
类似于 Ian Roberts 在回答中提出的表达式:
.//element[not(ancestor::element)] 
在这种情况下不选择任何内容。
更新:
正如 Michael Kay 所指出的,如果我们进一步概括这个问题并允许其他main元素出现在文档中的任何位置,那么这个答案中提出的表达式可能会选择“误报”。
这是一个更新的表达式(不再是纯/独立的 XPath 表达式,因为它使用 XSLT 函数current())在这种情况下仍然产生正确的计数:
.//element
   [(ancestor::main|ancestor::element)
                      [last()][self::main]
  and
    count(current()|ancestor::main[1]) = 1
   ]"/>