2010-06-03 2 views
2

Предположим, у меня есть этот документ.Как выбрать наиболее мелкие совпадающие элементы с XPath?

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

конечно, я ничего не получаю, так как А и его предок находятся в «в» пространстве имен.

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

Спасибо.

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

Кроме того, это не вопрос об пространствах имен. Это затруднительно с другими критериями соответствия.

+0

Хороший вопрос (+1). См. Мой ответ для единственного чистого решения XPath 1.0. :) –

ответ

0

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

+0

Спасибо, я сформулировал это несколько иначе (и, конечно, в C#), но техника сравнения отсчетов была умной. – harpo

+0

Это * не * вопрос XSLT. –

+0

@ Dimitre: это очень ясно, но соответствующий код C# тривиален для записи. –

2

Что об этом:

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

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

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

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

Спасибо за ответ. Я не использую XSLT здесь, или XPath 2.0. Действительно, .NET по-прежнему не поддерживает XPath 2.0. – harpo

+0

'глубокий-равный' XPath/XSLT 2.0 –

+0

@Pavel, я прошу отличаться. Но в любом случае я попытался использовать глубокий уровень, и .NET не распознает его. – harpo

1

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

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

Спасибо за вход, я пошел с чем-то очень похожим на это. Но поскольку глубина исходного узла была неизвестна, мне пришлось рассчитать ее на отдельном шаге. – harpo

+0

@harpo: В вашем случае был известен начальный узел, например. было ли у вас выражение XPath, выбрав начальный узел? –

+0

Нет, у меня просто была ссылка XmlNode. Фактически, я закончил создание выражений пути для выбранных узлов, используя процедуру, адаптированную из ответа Джона Скита на другой вопрос: http://stackoverflow.com/questions/241238/how-to-get-xpath-from-an-xmlnode- экземпляр-с/+241291 # +241291 – harpo

Смежные вопросы