使用SelectNodes和Xpath

时间:2015-04-23 04:51:38

标签: c# xml xpath

我正在编写一个解析XML文件的程序(包含Book内容)。

我做了什么,

XmlDoc = new XmlDocument();
XmlDoc.Load(path);
bookList = XmlDoc.GetElementsByTagName("book");
List<string> prices= new List<string>();

    foreach (XmlNode node in bookList)
    {
         XmlNode price = node["price"];
         prices.Add(price.InnerText);
    }
// to get the highest priced book(s)
prices.Sort();

我现在要做的是使用SelectNodes查找价格最高的图书,并将其作为XMLNodeList返回

//to store the highest price of a book
string highest = prices[0];

**// this is what i can't figure out
XmlNodeList expensiveList = XmlDoc.SelectNodes("descendant::book[price = highest]");**

感谢任何帮助,谢谢!

编辑:我设法通过在bookList中为节点创建foreach循环来解决这个问题,并使用if case来比较price.InnerText和最高。 它工作得很好,但我仍然想知道这是否可以用XPath完成。谢谢!

编辑#2:我知道可以使用不同的方法进行改进,我只想知道是否可以将字符串变量与节点值与XPath进行比较。

2 个答案:

答案 0 :(得分:1)

如果您决定使用Linq2XML,代码看起来会非常类似于: (因为我实际上没有你的XML,这就是我提出的)

// load from a file
var xDoc = XDocument.Load(path);

// find all nodes where the tagname is book
var books = xDoc.Descendants("book")

var expensiveList = books

  // make sure that the book has a price node
  .Where(b => b.Descendants("price").FirstOrDefault() != null

    // compare the first price node Value to highest
    && b.Descendants("price").First().Value.Equals("highest",
      StringComparison.OrdinalIgnoreCase))

  // lets only return up to 10
  .Take(10)

  // return what we found as List<XElement>
  .ToList();

如果价格实际上是一个整数,那么:

   int tempParse;

   ...     

  // make sure that the book has only 1 price
  .Where(b => b.Descendants("price").Count() == 1

    // price is actually an integer (you can replace with decimal)
    && int.TryParse(b.Descendants("price").First().Value, out tempParse))

  // make a temporary anonymous object to sort price
  .Select(b => new 
  {
    Book = b,
    Price = int.Parse(b.Descendants("price").First().Value)
  })

  // order the anonymous object by price
  .OrderByDescending(b => b.Price)

  // select only the books
  .Select(b => b.Book)

  // lets only return up to 10
  .Take(10)

   // return what we found as List<XElement>
  .ToList();

答案 1 :(得分:0)

一些建议:

  1. 您不应该使用字符串数组来存储价格。整数数组 会更好。
  2. 在将price.InnerText添加到列表之前验证它 - 它可能不是数值。
  3. 一旦你有一个整数数组 - 你可以对它进行排序并选择最大值。 要选择价格最高的图书,您可以使用

    之类的语法

    XmlNodeList expensiveList = XmlDoc.SelectNodes(“// book [price = highest]”);

  4. 如果您不想单独找出最高价格,可以直接获取具有最高价值的节点。见这个帖子。

    Selecting the min/max value of an attribute under multiple nodes in XPath 1.0

    希望这有帮助