Как выбрать самые мелкие совпадающие элементы в XPath? - PullRequest
2 голосов
/ 04 июня 2010

Допустим, у меня есть этот документ.

<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 )

Я получаю B, C и D. Но я не хочу D, потому что он вложен в другой элемент "a:".

Если я скажу

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

конечно, я ничего не получаю, так как и A, и его родитель находятся в пространстве имен "a".

Как я могу выбрать только B и C, то есть самые мелкие дочерние элементы, соответствующие пространству имен?

Спасибо.

Обратите внимание, что это XPath 1.0 (.NET 2), поэтому я не могу использовать префиксы в области видимости (которые, по-видимому, могут помочь).

Кроме того, это не совсем вопрос о пространствах имен. Проблема будет такой же, как и при других критериях соответствия.

Ответы [ 3 ]

2 голосов
/ 04 июня 2010

Что по этому поводу:

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

В XSLT это кажется простым (сохранить набор узлов в виде переменной), но я точно не знаю, как реализовать это в C #.

Редактировать: Продолжая работать над идеей использования счетчика, возможно, это сработает:

int nrParents = A.SelectNodes("ancestor-or-self::a:*", namespaceManager).Count(); // Or was it Size?
A.SelectNodes("//a:*[count(ancestor::a:*)!=" + nrParents + "]", namespaceManager)
1 голос
/ 04 июня 2010

Это не вопрос XSLT, поэтому здесь есть одно выражение XPath, которое выбирает два требуемых узла :

/*/*/descendant::a:*[not(count(ancestor::a:*) > 2)]
0 голосов
/ 04 июня 2010

Это невозможно сделать с одним выражением XPath 1.0. Расширяя ответ Марка, который использует 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....

...