HtmlAgilityPack y seleccionando Nodos y Subnodos

c# html-agility-pack xpath

Pregunta

Espero que alguien pueda ayudarme.

Digamos que tengo un documento html que contiene varios divs como este ejemplo:

<div class="search_hit">

    <span prop="name">Richard Winchester</span>
    <span prop="company">Kodak</span>
    <span prop="street">Arlington Road 1</span>

</div>
<div class="search_hit">

    <span prop="name">Ted Mosby</span>
    <span prop="company">HP</span>
    <span prop="street">Arlington Road 2</span>

</div>

Estoy usando HtmlAgilityPack para obtener el documento html. Lo que necesito saber es cómo puedo obtener los intervalos para cada "search_hit" -div?

Mi primer pensamiento fue algo como esto:

foreach (HtmlAgilityPack.HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']"))
{
     foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("//span[@prop]"))
     {

     }
}

Cada div debe ser un objeto con los intervalos incluidos como propiedades. I. e.

public class Record
    {
        public string Name { get; set; }
        public string company { get; set; }
        public string street { get; set; }
    }

Y esta lista se llenará entonces:

public List<Record> Results = new List<Record>();

Pero el XPATH que estoy usando no está haciendo una búsqueda en el subnodo como debería hacer. Parece que busca todo el documento una y otra vez.

Quiero decir que ya lo tengo funcionando de esa manera que acabo de ver los tramos de toda la página. Pero entonces no tengo ninguna relación entre los vanos y divs. Medios: Ya no sé qué intervalo está relacionado con qué div.

¿Alguien sabe una solución? Ya he jugado todo lo que estoy totalmente confundido ahora :)

Cualquier ayuda es apreciada!

Respuesta aceptada

Lo siguiente funciona para mí. Lo importante es que BeniBela señaló que agregar un punto en la segunda llamada a 'SelectNodes'.

List<Record> lstRecords=new List<Record>();
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']"))
{
  Record record=new Record();
  foreach (HtmlNode node2 in node.SelectNodes(".//span[@prop]"))
  {
    string attributeValue = node2.GetAttributeValue("prop", "");
    if (attributeValue == "name")
    {
      record.Name = node2.InnerText;
    }
    else if (attributeValue == "company")
    {
      record.company = node2.InnerText;
    }
    else if (attributeValue == "street")
    {
      record.street = node2.InnerText;
    }
  }
  lstRecords.Add(record);
}

Respuesta popular

Si usas // , comienza desde el documento.

Utilice .// para buscar todo desde el nodo actual

 foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]"))

O elimine el prefijo por completo para buscar solo hijos directos:

 foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("span[@prop]"))


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué