Selecionar nós usando a navegação XPath

O DOM (Document Object Model) XML contém métodos que permitem que você use a navegação da linguagem XPath para consultar informações no DOM. Você pode usar a linguagem XPath para localizar um único nó específico ou todos os nós que correspondam a alguns critérios.

Métodos de seleção XPath

As classes DOM fornecem dois métodos de seleção XPath: o método SelectSingleNode e o método SelectNodes. O método SelectSingleNode retorna o primeiro nó que corresponde aos critérios de seleção. O método SelectNodes retorna um XmlNodeList que contém os nós correspondentes.

O exemplo a seguir usa o método SelectSingleNode para selecionar o primeiro nó book, no qual o sobrenome do autor atende a critérios específicos. O arquivo bookstore.xml (que é fornecido no final deste tópico) é usado como o arquivo de entrada.

Dim doc As New XmlDocument()  
doc.Load("bookstore.xml")  
Dim root As XmlNode = doc.DocumentElement  
  
' Add the namespace.  
Dim nsmgr As New XmlNamespaceManager(doc.NameTable)  
nsmgr.AddNamespace("bk", "urn:newbooks-schema")  
  
' Select and display the first node in which the author's
' last name is Kingsolver.  
Dim node As XmlNode = root.SelectSingleNode( _  
     "descendant::bk:book[bk:author/bk:last-name='Kingsolver']", nsmgr)  
Console.WriteLine(node.InnerXml)  
// Load the document and set the root element.  
XmlDocument doc = new XmlDocument();  
doc.Load("bookstore.xml");  
XmlNode root = doc.DocumentElement;  
  
// Add the namespace.  
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);  
nsmgr.AddNamespace("bk", "urn:newbooks-schema");  
  
// Select and display the first node in which the author's
// last name is Kingsolver.  
XmlNode node = root.SelectSingleNode(  
    "descendant::bk:book[bk:author/bk:last-name='Kingsolver']", nsmgr);  
Console.WriteLine(node.InnerXml);  

O exemplo a seguir usa o método SelectNodes para selecionar todos os nós de livros em que o preço é maior do que um valor especificado. O preço de cada livro na lista selecionada é reduzido programaticamente em dez por cento. Finalmente, o arquivo atualizado é gravado no console. O arquivo bookstore.xml (que é fornecido no final deste tópico) é usado como o arquivo de entrada.

' Load the document and set the root element.  
Dim doc As New XmlDocument()  
doc.Load("bookstore.xml")  
Dim root As XmlNode = doc.DocumentElement  
  
' Add the namespace.  
Dim nsmgr As New XmlNamespaceManager(doc.NameTable)  
nsmgr.AddNamespace("bk", "urn:newbooks-schema")  
  
' Select all nodes where the book price is greater than 10.00.  
Dim nodeList As XmlNodeList = root.SelectNodes( _  
     "descendant::bk:book[bk:price>10.00]", nsmgr)  
For Each book As XmlNode In nodeList  
     Dim price As Double  
     price = Math.Round(Convert.ToSingle( _  
          book.LastChild.InnerText) * 0.9, 2)  
     book.LastChild.InnerText = price.ToString()  
Next  
  
' Display the updated document.  
doc.Save(Console.Out)  
// Load the document and set the root element.  
XmlDocument doc = new XmlDocument();  
doc.Load("bookstore.xml");  
XmlNode root = doc.DocumentElement;  
  
// Add the namespace.  
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);  
nsmgr.AddNamespace("bk", "urn:newbooks-schema");  
  
// Select all nodes where the book price is greater than 10.00.  
XmlNodeList nodeList = root.SelectNodes(  
     "descendant::bk:book[bk:price>10.00]", nsmgr);  
foreach (XmlNode book in nodeList)  
{  
     // Discount prices by 10%.  
     double price;  
     price = Math.Round(Convert.ToSingle(  
          book.LastChild.InnerText) * 0.9, 2);  
     book.LastChild.InnerText = price.ToString();  
}  
  
// Display the updated document.  
doc.Save(Console.Out);  

Os exemplos acima iniciam a consulta XPath no elemento de documento. A definição do ponto de partida para a consulta XPath define o nó de contexto, que é o ponto de partida para a consulta XPath. Se você não deseja começar no elemento de documento, mas a partir do primeiro elemento filho do documento, você pode codificar a instrução de seleção da seguinte maneira:

doc.DocumentElement.FirstChild.SelectNodes(. . . )  
this doc.DocumentElement.FirstChild.SelectNodes(. . .);  

Todos os objetos XmlNodeList são sincronizados com o documento subjacente. Portanto, se você iterar pela lista de nós e modificar o valor de um nó, esse nó também será atualizado no documento de origem. Observe no exemplo anterior que, quando um nó é modificado no XmlNodeList selecionado, o documento subjacente também é modificado.

Observação

Quando o documento subjacente é modificado, é aconselhável executar novamente a seleção. Se o nó modificado for um que possa fazer com que o nó seja adicionado à lista de nós quando não tiver sido anteriormente, ou que agora faça com que ele seja removido da lista, não haverá nenhuma garantia de que a lista de nós agora esteja exata.

Namespaces em expressões XPath

As expressões XPath podem incluir namespaces A resolução de namespace tem suporte com o uso do XmlNamespaceManager. Se a expressão XPath incluir um prefixo, o par de prefixo e URI de namespace deverá ser adicionado a XmlNamespaceManager, e XmlNamespaceManager será passado ao método SelectNodes(String, XmlNamespaceManager) ou SelectSingleNode(String, XmlNamespaceManager). Observe que os exemplos de código acima usam XmlNamespaceManager para resolver o namespace do documento bookstore.xml.

Observação

Se a expressão XPath não incluir um prefixo, presume-se que o URI do namespace seja o namespace vazio. Se o XML incluir um namespace padrão, você ainda deverá adicionar um prefixo e um URI de namespace a XmlNamespaceManager; caso contrário, nenhum nó será selecionado.

Arquivo de entrada

A seguir está o arquivo bookstore.xml que é usado como o arquivo de entrada nos exemplos deste tópico:

<?xml version='1.0'?>  
<bookstore xmlns="urn:newbooks-schema">  
  <book genre="novel" style="hardcover">  
    <title>The Handmaid's Tale</title>  
    <author>  
      <first-name>Margaret</first-name>  
      <last-name>Atwood</last-name>  
    </author>  
    <price>19.95</price>  
  </book>  
  <book genre="novel" style="other">  
    <title>The Poisonwood Bible</title>  
    <author>  
      <first-name>Barbara</first-name>  
      <last-name>Kingsolver</last-name>  
    </author>  
    <price>11.99</price>  
  </book>  
  <book genre="novel" style="paperback">  
    <title>The Bean Trees</title>  
    <author>  
      <first-name>Barbara</first-name>  
      <last-name>Kingsolver</last-name>  
    </author>  
    <price>5.99</price>  
  </book>  
</bookstore>  

Confira também