Как использовать XPath с XElement или LINQ? - PullRequest
75 голосов
/ 04 сентября 2010

Рассмотрим следующий 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>

Я ищу очень короткий способ получить только значение элемента <hash>.Я пытался:

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

Но это не работает.Можно ли предоставить запрос XPath для XElement?Я могу сделать это с более старой System.Xml платформой, сделав что-то вроде:

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

Есть ли что-то подобное в пространстве имен LINQ?


ОБНОВЛЕНИЕ:

Обдумав это, я нашел способ сделать то, что я пытаюсь сделать:

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

Мне все равно было бы интересно узнать, есть ли у кого-нибудь лучшее решение?

Ответы [ 5 ]

132 голосов
/ 04 сентября 2010

Чтобы использовать XPath с LINQ to XML, добавьте объявление использования для System.Xml.XPath, это приведет к расширению методов System.Xml.XPath.Extensions.

В вашем примере:

var value = (string)xml.XPathEvaluate("/response/data/hash");
38 голосов
/ 04 сентября 2010

Другие совершенно разумно предложили, как использовать «родные» запросы LINQ to XML, чтобы делать то, что вы хотите.

Однако в интересах предоставления множества альтернатив рассмотрим XPathSelectElement, XPathSelectElements и XPathEvaluate для оценки выражений XPath по XNode (это все методы расширения в XNode). Вы также можете использовать CreateNavigator, чтобы создать XPathNavigator для XNode.

Лично я большой поклонник использования LINQ to XML API напрямую, так как я большой поклонник LINQ, но если вам удобнее работать с XPath, вышеописанное может вам помочь.

14 голосов
/ 04 сентября 2010

Смотрите, когда имеете дело с LINQ to XML, почему вы не используете LINQ для получения реального объекта.

Потомки находят каждый элемент из всего XML и перечисляют все объекты, которые соответствуют указанному имени. Так что в вашем случае хеш это имя, которое он находит.

Итак, вместо того, чтобы делать

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

Я бы распался, как:

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

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

Таким образом, вы также можете получить атрибуты, элементы узлов и т. Д.

Проверьте эту статью, чтобы получить ясное представление об этом, чтобы оно помогло. http://www.codeproject.com/KB/linq/LINQtoXML.aspx Я надеюсь, что это поможет вам.

8 голосов
/ 24 октября 2013

Вы можете использовать метод .Element () для объединения элементов в XPath-подобную структуру.

Например:

XElement xml = XElement.Parse(@"...your xml...");
XElement hash = xml.Element("data").Element("hash");
2 голосов
/ 02 февраля 2014

Я попытался создать каркас LINQesq для генерации xpath. Позволяет описать xpath с помощью лямбда-выражений c #

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

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

Не уверен, что это полезно в этом контексте, но вы можете найти документацию здесь:

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

...