如何使用XPath选择最浅的匹配元素?

时间:2010-06-03 21:37:45

标签: .net xpath xpath-1.0

假设我有这份文件。

<a:Root>
    <a:A>
        <title><a:B/></title>
        <a:C>
            <item><a:D/></item>
        </a:C>
    </a:A>
</a:Root>

我将XmlNode设置为<a:A>元素。

如果我说

A.SelectNodes( "//a:*", namespaceManager )

我得到BCD。但我不想要D,因为它嵌套在另一个“a:”元素中。

如果我说

A.SelectNodes( "//a:*[not(ancestor::a:*)]", namespaceManager )

当然,我什么都没得到,因为A和它的父都在“a”命名空间中。

如何选择BC,即与名称空间匹配的最浅的孩子?

感谢。

注意,这是XPath 1.0(.NET 2),因此我不能使用范围内前缀(它看起来会有所帮助)。

此外,这不是关于命名空间的问题。窘境与其他匹配标准相同。

3 个答案:

答案 0 :(得分:2)

这个怎么样:

<xsl:variable name="parents" select="ancestor-or-self::a:*" />
<xsl:value-of select="//a:*[not(deep-equal(ancestor::a:*, $parent))]" />

在XSLT中,这似乎很简单(将节点集存储为变量),但我不知道如何在C#中实现它。

编辑:进一步研究使用count的想法,这可能有用:

int nrParents = A.SelectNodes("ancestor-or-self::a:*", namespaceManager).Count(); // Or was it Size?
A.SelectNodes("//a:*[count(ancestor::a:*)!=" + nrParents + "]", namespaceManager)

答案 1 :(得分:1)

这不是XSLT问题,所以这里有一个XPath表达式,用于选择想要的两个节点

/*/*/descendant::a:*[not(count(ancestor::a:*) > 2)]

答案 2 :(得分:0)

单个XPath 1.0表达式无法做到这一点。扩展Marc使用XSLT的答案,你可以为1.0:

执行此操作
<xsl:variable name="n" select="count(ancestor-or-self::a:*)" />
<xsl:variable name="result" select=".//a:*[count(ancestor::a:*) = $n]" />

或等效的C#调用Select...