Seleziona il nodo in base alle proprietà di pari livello: HtmlAgilityPack - C #

c# html-agility-pack html-parsing

Domanda

Ho un documento HTML strutturato come segue

<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>

Ho bisogno di analizzare i valori dei <strong> -tags nella string corrispondente, a seconda del valore che ha il <span> .

Ho il seguente:

String vintage;
String sugar;
String abv;

A partire da ora, eseguo il ciclo di ogni nodo figlio del canale beverageFacts controllando i valori per analizzarlo sulla string corrispondente corretta. Il codice che ho finora per ottenere il valore "Vintage" è il seguente, sebbene il risultato sia sempre null .

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

Credo che la mia selezione dei nodi non sia corretta, ma non riesco a capire come farlo correttamente nel modo più efficiente.

C'è un modo semplice per raggiungere questo obiettivo?


Modifica 2013-07-29

Ho provato a rimuovere gli spazi bianchi come suggerito da enricoariel nei commenti usando il seguente codice

        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);

Il risultato è ancora

 String vintage = null;

Risposta accettata

Guardando il markup HTML, mi sono reso conto che non andavo abbastanza in profondità nei nodi. Inoltre, come ha sottolineato enricoariel, ci sono spazi bianchi che non pulisco correttamente. Saltando il fratello che è lo spazio bianco, e invece salta al seguente, ottengo il risultato corretto.

        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);

uscirà

Vintage: 2007

Ho decodificato l'HTML per ottenere il risultato formattato correttamente.

Lezioni imparate!


Risposta popolare

per riassumere penso che la soluzione migliore sarebbe spogliare tutti gli spazi bianchi usando una regex prima di recuperare il valore 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;



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché