ti-enxame.com

Como usar o XPath com XElement ou LINQ?

Considere o seguinte XML:

<response>
  <status_code>200</status_code>
  <status_txt>OK</status_txt>
  <data>
    <url>http://bit.ly/b47LVi</url>
    <hash>b47LVi</hash>
    <global_hash>9EJa3m</global_hash>
    <long_url>http://www.tumblr.com/docs/en/api#api_write</long_url>
    <new_hash>0</new_hash>
  </data>
</response>

Estou procurando uma maneira muito curta de obter apenas o valor do <hash> elemento. Eu tentei:

var hash = xml.Element("hash").Value;

Mas isso não está funcionando. É possível fornecer uma consulta XPath para um XElement? Eu posso fazer isso com os mais velhos System.Xml framework, fazendo algo como:

xml.Node("/response/data/hash").Value

Existe algo assim em um espaço para nome LINQ?


ATUALIZAR:

Depois de brincar um pouco mais com isso, encontrei uma maneira de fazer o que estou tentando fazer:

var hash = xml.Descendants("hash").FirstOrDefault().Value;

Eu ainda estaria interessado em ver se alguém tem uma solução melhor?

75
Paul Fryer

Para usar o XPath com LINQ to XML, adicione uma declaração de uso para System.Xml.XPath, isso trará os métodos de extensão de System.Xml.XPath.Extensions no escopo.

No seu exemplo:

var value = (string)xml.XPathEvaluate("/response/data/hash");
133
Richard

Outros sugeriram inteiramente como usar consultas LINQ to XML "nativas" para fazer o que você deseja.

No entanto, no interesse de fornecer várias alternativas, considere XPathSelectElement , XPathSelectElements e XPathEvaluate para avaliar expressões XPath em relação a um XNode (todos são métodos de extensão em XNode). Você também pode usar CreateNavigator para criar um XPathNavigator para um XNode.

Pessoalmente, sou um grande fã de usar a API LINQ to XML diretamente, pois sou um grande fã de LINQ, mas se você se sentir mais à vontade com o XPath, as opções acima podem ajudá-lo.

38
Jon Skeet

Veja, ao lidar com o LINQ to XML, por que você não usa o LINQ para obter o objeto real.

Os descendentes encontram cada elemento de todo o XML e listam todos os objetos que correspondem ao nome especificado. Portanto, no seu caso, hash é o nome que ele encontra.

Então, ao invés de fazer

var hash = xml.Descendants("hash").FirstOrDefault().Value;

Eu me separaria como:

var elements = xml.Descendants("hash");
var hash = elements.FirstOrDefault();

if(hash != null)
 hash.Value // as hash can be null when default. 

Dessa forma, você também pode obter atributos, elementos de nós etc.

Confira este artigo para ter uma idéia clara sobre o assunto e ajudá-lo. http://www.codeproject.com/KB/linq/LINQtoXML.aspx Espero que isso ajude você.

14
abhishek

Você pode usar o método .Element () para encadear os elementos para formar uma estrutura semelhante ao XPath.

Para o seu exemplo:

XElement xml = XElement.Parse(@"...your xml...");
XElement hash = xml.Element("data").Element("hash");
8
panpawel

Eu tentei criar uma estrutura LINQesq para gerar xpath. Permite descrever o xpath usando expressões c # lambda

var xpath = CreateXpath.Where(e => e.TargetElementName == "td" && e.Parent.Name == "tr");

var xpath = CreateXpath.Where(e => e.TargetElementName == "td").Select(e => e.Text);

Não tenho certeza se isso é útil nesse contexto, mas você pode encontrar documentação aqui:

http://www.syntaxsuccess.com/viewarticle/how-to-create-xpath-using-linq

2
TGH