Seleccione el nodo basado en las propiedades de los hermanos - HtmlAgilityPack - C #

c# html-agility-pack html-parsing

Pregunta

Tengo un documento HTML que está estructurado de la siguiente manera

<ul class="beverageFacts">
<li>
    <span>Vintage</span> 
    <strong>2007&nbsp;</strong>
</li>
<li>
    <span>ABV</span> 
    <strong>13,0&nbsp;%</strong>
</li>
<li>
    <span>Sugar</span> 
    <strong>5&nbsp;gram/liter</strong>
</li>

Necesito analizar los valores de las etiquetas <strong> a las string correspondientes, dependiendo del valor que tenga la etiqueta <span> .

Tengo los siguientes

String vintage;
String sugar;
String abv;

A partir de ahora, estoy bucle a través de cada nodo hijo de los beverageFacts -node comprobación de los valores a analizar a la correspondiente correcto string . El código que tengo hasta ahora para obtener el valor "Vintage" es el siguiente, aunque el resultado siempre es null .

HtmlNodeCollection childNodes = bevFactNode.ChildNodes;
foreach (HtmlNode subNode in childNodes)
{
    if (subNode.InnerText.TrimStart() == "Vintage")
        vintage = subNode.NextSibling.InnerText.Trim();
}

Creo que mi selección de los nodos es incorrecta, pero no puedo descubrir cómo hacerlo correctamente de la manera más eficiente.

¿Hay una manera fácil de lograr esto?


Editar 2013-07-29

He intentado eliminar los espacios en blanco según lo sugerido por enricoariel en los comentarios utilizando el siguiente código

        HtmlAgilityPack.HtmlDocument page = new HtmlWeb().Load("http://www.systembolaget.se/" + articleID);

        string cleanDoc = Regex.Replace(page.DocumentNode.OuterHtml, @"\s*(?<capture><(?<markUp>\w+)>.*<\/\k<markUp>>)\s*", "${capture}", RegexOptions.Singleline);

        HtmlDocument cleanPage = new HtmlDocument();
        cleanPage.LoadHtml(cleanDoc);

El resultado es todavía

 String vintage = null;

Respuesta aceptada

Mirando el código HTML, me di cuenta de que no fui lo suficientemente profundo en los nodos. Además, como señaló enricoariel, hay espacios en blanco que no limpio correctamente. Al omitir al hermano que es el espacio en blanco, y en lugar de saltar al siguiente, obtengo el resultado correcto.

        foreach (HtmlNode bevFactNode in bevFactsNodes)
        {
            HtmlNodeCollection childNodes = bevFactNode.ChildNodes;
            foreach (HtmlNode node in childNodes)
            {
                foreach(HtmlNode subNode in node.ChildNodes)
                {
                    if (subNode.InnerText.Trim() == "Årgång")
                        vintage = HttpUtility.HtmlDecode(subNode.NextSibling.NextSibling.InnerText.Trim());
                }
            }
        }
        Console.WriteLine("Vintage: " + vintage);

dará salida

Vintage: 2007

Decodifiqué el HTML para obtener el resultado formateado correctamente.

¡Lecciones aprendidas!


Respuesta popular

para resumir, creo que la mejor solución sería eliminar todos los espacios en blanco utilizando una expresión regular antes de recuperar el valor nextSibling:

    string myHtml =
    @"
    <ul class='beverageFacts'>
    <li>
        <span>Vintage</span> 
        <strong>2007&nbsp;</strong>
    </li>
    <li>
        <span>ABV</span> 
        <strong>13,0&nbsp;%</strong>
    </li>
    <li>
        <span>Sugar</span> 
        <strong>5&nbsp;gram/liter</strong>
    </li>";
    //Remove space after and before tag
myHtml = Regex.Replace(myHtml, @"\s+<", "<", RegexOptions.Multiline | RegexOptions.Compiled);
myHtml = Regex.Replace(myHtml, @">\s+", "> ", RegexOptions.Compiled | RegexOptions.Multiline);

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(myHtml.Replace("/r", "").Replace("/n", "").Replace("/r/n", "").Replace("  ", ""));
doc.OptionFixNestedTags = true;

HtmlNodeCollection vals = doc.DocumentNode.SelectNodes("//ul[@class='beverageFacts']//span");

var myNodeContent = string.Empty;
foreach (HtmlNode val in vals)
{
    if (val.InnerText == "Vintage")
    {
        myNodeContent = val.NextSibling.InnerText;
    }
}

return myNodeContent;


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é