简体   繁体   中英

How do I perform this XPath query with Linq?

In the following code I am using XPath to find all of the matching nodes using XPath, and appending the values to a StringBuilder.

StringBuilder sb = new StringBuilder();
foreach (XmlNode node in this.Data.SelectNodes("ID/item[@id=200]/DAT[1]/line[position()>1]/data[1]/text()"))
{
    sb.Append(node.Value);
}
return sb.ToString();

How do I do the same thing, except using Linq to XML instead? Assume that in the new version, this.Data is an XElement object.

You can still use XPath with a XElement. You have to include the System.Xml.XPath namespace since its an extension method

var xml = XDocument.Parse("<xml></xml>");
var elements = xml.XPathSelectElements("ID/item[@id=200]/DAT[1]/line[position()>1]/data[1]/text()");

I have created an open source helper library that let's you generate xpath expressions using Linq-esq expressions. Not sure if it is helpful in your context, but posting the link to the API

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

Query syntax would look something like this.

var nodes = from item in Data.Elements("item")
            where item.Attribute("id").Value == "200"
            let dat = item.Element("DAT")
            from line in dat.Elements("line").Skip(1)
            let data = line.Element("data")
            select data;

var sb = new StringBuilder();
foreach (var node in nodes)
    sb.Append(node.Value);

... this would get rid of the possible nullref exceptions and would get rid of the foreach loop.

var nodes = from item in Data.Elements("item")
            let id = item.Attribute("id")
            where id != null && id.Value == "200"
            let dat = item.Element("DAT")
            where dat != null
            from line in dat.Elements("line").Skip(1)
            let data = line.Element("data")
            where data != null
            select data.Value;
return nodes.Aggregate(new StringBuilder(), (sb, r) => sb.Append(r))
            .ToString();

You can try something like that :

var query = 
    from id in this.Data.Elements("ID")                      // ID
    from item in id.Elements("item")                         // /item
    where item.Attribute("id").Value == "200"                // [@id=200]
    let dat in item.Elements("DAT").ElementAtOrDefault(1)    // /DAT[1]
    where dat != null                                        // (ensure there is an element at index 1)
    from line in dat.Elements("line").Skip(1)                // /line[position()>1]
    let data in line.Elements("data").ElementAtOrDefault(1)  // /data[1]
    where data != null                                       // (ensure there is an element at index 1)
    select data                                              // /text()

StringBuilder sb = new StringBuilder();
foreach(XElement data in query)
{
    sb.Append(data.Value);
}
return sb.ToString();

As you can see, it's not really more convenient than XPath, so you should probably keep using XPath (as explained in Pierre-Alain's answer)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM