Pergunta
Estou usando XPath no .NET para analisar um documento XML, nos moldes de:
XmlNodeList lotsOStuff = doc.SelectNodes("//stuff");
foreach (XmlNode stuff in lotsOStuff) {
XmlNode stuffChild = stuff.SelectSingleNode("//stuffChild");
// ... etc
}
O problema é que a consulta XPath para stuffChild
está sempre devolvendo o filho do primeiro stuff
elemento, nunca o resto.O XPath não pode ser usado para consultar um indivíduo? XMLElement
?
Solução
//
no início de uma expressão XPath começa na raiz do documento.Experimente ".//stuffChild"..é uma abreviação de self::node(), que definirá o contexto para a pesquisa, e // é uma abreviação do eixo descendente.
Então você tem:
XmlNode stuffChild = stuff.SelectSingleNode(".//stuffChild");
que se traduz em:
xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant::stuffChild");
xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant-or-self::stuffChild");
No caso em que o nó filho possa ter o mesmo nome que o pai, você deve usar a sintaxe um pouco mais detalhada a seguir, para garantir que não selecione novamente o pai:
xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant::stuffChild");
Observe também que se "stuffChild" for descendente direto de "stuff", você poderá omitir completamente os prefixos e apenas selecionar "stuffChild".
XmlNode stuffChild = stuff.SelectSingleNode("stuffChild");
O Escolas W3 O tutorial contém informações úteis em um formato fácil de digerir.
Outras dicas
O //
você usa na frente de stuffChild
significa que você está procurando stuffChild
elementos, começando pela raiz.
Se você deseja iniciar a partir do nó atual (descendentes do nó atual), você deve usar .//
, como em:
stuff.SelectSingleNode(".//stuffChild");
Se "stuffChild" for um nó filho de "stuff", então seu xpath deverá ser apenas:
XmlNode stuffChild = stuff.SelectSingleNode("stuffChild");
Selecionar um único nó significa que você precisa apenas do primeiro elemento.Então, a melhor solução é:
XmlNode stuffChild = stuff.SelectSingleNode("descendant::stuffChild[1]");