XPath SelectNodes в .NET

<Document>
  <A> 
    <B> 
      <C></C>
    </B>
  </A>
  <E>
   <F>
    <C></C>
   </F>
   <G>
    <C></C>
  </G>
 </E>
</Document>

Если я загружаю вышеуказанный XML в XmlDocument и делаю SelectSingleNode на A, используя запрос XPath//C

XmlNode oNode = oDocument.SelectSingleNode("E");
XmlNodeList oNodeList = oNode.SelectNodes("//C");

почему он возвращает узлы из под B, когда то, что я ожидал бы, приведет к тому, что он вернет только узлы из под E

Имеют смысл?

Изменить: Как я могу сделать это только с этого node?

Ответы

Ответ 1

Просто: ведущий//означает "на любом уровне" в том же документе, что и выбранный node.

Из spec:

  • //para выбирает всех потомков абзаца корня документа и, таким образом, выбирает все элементы para в том же документе, что и контекст node
  • .//para выбирает потомки пара элемента контекста node

Ответ 2

Задание .//C приведет к тому, что вы хотите, иначе XPath начнется с корня документа, а не с текущего node.

Путаница находится в определении // из стандарта XPath следующим образом:

//не подходит для /Потомок или-я:: node()/. Для Например, //para не подходит для /Потомок или-я:: node()/ребенок:: пункт и поэтому выберет любой элемент para в документ (даже элемент пара, который будет выбран элемент документа по //para, поскольку элемент документа node является потомком корня node); div//para не подходит для DIV/потомок или-я:: node()/ребенок:: пункт и поэтому выберет все параграфы потомки детей div.

Поскольку // является коротким для /descendant-or-self::node()/, он начинается с уровня документа, если вы не укажете node в начале.

Ответ 3

//C - все C-узлы во всем документе

/E//C будет только C-узлами под E

/C будет только корнем C node

См. ссылка на синтаксис xpath

Ответ 4

В Спецификация XPATH вы найдете ниже 2.5 следующего утверждения:

//para выбирает весь параграф потомки корня документа и таким образом, выбирает все пара-элементы в тот же документ, что и контекст node

то есть. поведение, которое вы наблюдаете, действительно. Вы должны сделать что-то вроде "/E//C"