2015-04-23 3 views
1

Я пишу программу для анализа XML-файла (с содержимым книги).Xml Анализ с использованием SelectNodes и Xpath

То, что я сделал,

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]");** 

Любая помощь приветствуется, спасибо !

EDIT: Мне удалось обойти это, сделав цикл foreach для узлов в bookList с if, чтобы сравнить цены. InnerText с наивысшим. Он работает отлично, но я все равно хотел бы знать, можно ли это сделать с XPath. Благодаря!

EDIT # 2: Я понимаю, что его можно улучшить при использовании разных подходов, я просто хочу знать, можно ли сравнить строковую переменную с значениями узлов с помощью XPath.

+0

какой-либо причина вы не используете Linq2Xml? Linq предоставляет очень простой способ выбора, сортировки, упорядочивания и фильтрации узлов XML. –

+0

Существует такой вид, упомянутый в [social.msdn] (https://social.msdn.microsoft.com/Forums/en-US/60ba8eef-4318-4361-a434-e07efc7bdc77/xml-filter-and-sort?forum = xmlandnetfx). ты это пробовал? – lloyd

+0

@Erik Я не знаком с Linq2Xml, но я загляну в него. Я исследовал Xpath почти на час и нашел много способов сравнить значения, но не переменные, поэтому вопрос. – Ankit

ответ

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(); 
+0

Интересно. Это выглядит более тщательным и прямым образом. Я обязательно попробую. Спасибо Erik – Ankit

+0

Я добавил код, если цена является фактическим значением. –

0

Некоторые предложения:

  1. Нельзя брать строковый массив для хранения цен. Целочисленный массив будет лучше.
  2. Подтвердить цену.InnerText перед добавлением его в список - возможно, это не числовое значение.
  3. Как только у вас есть целочисленный массив, вы можете отсортировать его и выбрать макс. Чтобы выбрать книгу по максимальной цене, вы можете использовать синтаксис как

    XmlNodeList дорогойList = XmlDoc.SelectNodes ("// book [price = maximum]");

Если вы не хотите узнать самую высокую цену отдельно - есть способ захватить узел с наибольшим значением напрямую. Смотрите эту тему.

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

Надеется, что это помогает

Смежные вопросы