XPath, select multiple elements from multiple nodes in HTML

c# html html-agility-pack xpath

Question

I just can't figure this one.

I have to search through all nodes that have classes with "item extend featured" values in it (code below). In those classes I need to select every InnerText of <h2 class="itemtitle"> and href value in it, plus all InnerTexts from <div class="title-additional">.

<li class="item extend featured">
    <div class="title-box">
        <h2 class="itemtitle">
            <a target="_top" href="www.example.com/example1/example2/exammple4/example4" title="PC Number 1">PC Number 1</a>
        </h2>
        <div class="title-additional">
            <div class="title-km">150 km</div>
            <div class="title-year">2009</div>
            <div class="title-price">250 €</div>
        </div>

The output should be something like this:

Title:
href:
Title-km:
Title-year:
Title-Price:
--------------


Title:
href:
Title-km:
Title-year:
Title-Price:
--------------

So, the question is, how to traverse through all "item extend featured" nodes in html and select items I need above from each node?

As I understand, something like this should work but it breaks halfway

EDIT: I just noticed, there are ads on the site that share the exact same class and they obviously don't have the elements I need. More problems to think about.

var items1 = htmlDoc.DocumentNode.SelectNodes("//*[@class='item extend featured']");

foreach (var e in items1)
{
   var test = e.SelectSingleNode(".//a[@target='_top']").InnerText;
   Console.WriteLine(test);
}

Accepted Answer

var page = new HtmlDocument();
page.Load(path);
var lists = page.DocumentNode.SelectNodes("//li[@class='item extend featured']");
foreach(var list in lists)
{
    var link = list.SelectSingleNode(".//*[@class='itemtitle']/a");
    string title = link.GetAttributeValue("title", string.Empty);
    string href = link.GetAttributeValue("href", string.Empty);
    string km = list.SelectSingleNode(".//*[@class='title-km']").InnerText;
    string year = list.SelectSingleNode(".//*[@class='title-year']").InnerText;
    string price = list.SelectSingleNode(".//*[@class='title-price']").InnerText;
    Console.WriteLine("Title: %s\r\n href: %s\r\n Title-km: %s\r\n Title-year: %s\r\n Title-Price: %s\r\n\r\n", title, href, km, year, price);
}

Popular Answer

What you are trying to achieve requires multiple XPath expressions as you can't return multiple results at different levels using one query (unless you use Union perhaps).

What you might be looking for is something similar to this:

var listItems = htmlDoc.DocumentNode.SelectNodes("//li[@class='item extend featured']");

foreach(var li in listItems) {
    var title = li.SelectNodes("//h2/a/text()");
    var href = li.SelectNodes("//h2/a/@href");
    var title_km = li.SelectNodes("//div[@class='title-additional']/div[@class='title-km']/text()");
    var title_... // other divs
}

Note: code not tested




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why