obtenir tous les nœuds et son contenu à l'aide de htmldocument / HtmlAgilityPack

c# html html-agility-pack uwp

Question

Je dois obtenir tous les nœuds à partir d'un fichier HTML, puis de ces nœuds, il me faut le texte et les sous-nœuds, et la même chose, mais à partir de ces sous-sous-nœuds. Par exemple, j'ai ce code HTML:

<p>This <b>is a <a href="">Link</a></b> with <b>bold</b></p>

J'ai donc besoin d'un moyen pour obtenir le nœud p , puis le texte non formaté (this), le texte uniquement en gras ( est a ), le lien en gras ( Link ) et le reste du texte formaté et non formaté.

Je sais qu'avec htmldocument, je peux sélectionner tous les nœuds et sous-nœuds, mais comment puis-je obtenir le texte avant le sous-nœud, puis le sous-nœud et ses sous-nœuds text / afin que je puisse créer la version rendue du HTML ("Ceci est un lien avec gras ")?

Veuillez noter que l'exemple ci-dessus est simple. Le HTML aurait des éléments plus complexes tels que liste, cadres, liste numérotée, texte au format triple, etc. Notez également que le rendu n'est pas un problème. Je l'ai déjà fait mais d'une autre manière. Ce dont j'ai besoin, c'est de la partie pour obtenir les nœuds et son contenu uniquement. De plus, je ne peux ignorer aucun noeud, je ne peux donc pas filtrer par rien. Et le noeud principal pourrait commencer comme p, div, frame, ul, etc.

Réponse acceptée

Après avoir examiné le fichier htmldoc et ses propriétés, et grâce à l'observation de @HungCao, j'ai obtenu un moyen simple et efficace d'interpréter un code HTML.

Mon code est un peu plus complexe pour l'ajouter à titre d'exemple, je vais donc en publier une version allégée.

Tout d'abord, le htmlDoc doit être chargé. Cela pourrait être n'importe quelle fonction:

HtmlDocument htmlDoc = new HtmlDocument();
string html = @"<p>This <b>is a <a href="""">Link</a></b> with <b>bold</b></p>";
htmlDoc.LoadHtml(html);

Ensuite, nous devons interpréter chaque nœud "principal" (p dans ce cas) et, en fonction de son type, nous devons charger un LoopFunction (InterNode)

HtmlNodeCollection nodes = htmlDoc.DocumentNode.ChildNodes;

foreach (HtmlNode node in nodes)
{
    if(node.Name.ToLower() == "p") //Low the typeName just in case
    {
        Paragraph newPPara = new Paragraph();
        foreach(HtmlNode childNode in node.ChildNodes)
        {
            InterNode(childNode, ref newPPara);
        }
        richTextBlock.Blocks.Add(newPPara);
    }
}

Veuillez noter qu'il existe une propriété appelée "NodeType", mais elle ne renverra pas le type correct. Donc, utilisez plutôt la propriété "Name" (notez également que la propriété Name dans htmlNode n'est pas la même chose que l'attribut Name dans HTML).

Enfin, nous avons la fonction InterNode qui ajoutera des lignes au paragraphe référé (ref)

public bool InterNode(HtmlNode htmlNode, ref Paragraph originalPar)
{
    string htmlNodeName = htmlNode.Name.ToLower();

    List<string> nodeAttList = new List<string>();
    HtmlNode parentNode = htmlNode.ParentNode;
    while (parentNode != null) {
        nodeAttList.Add(parentNode.Name);
        parentNode = parentNode.ParentNode;
    } //we need to get it multiple types, because it could be b(old) and i(talic) at the same time.

    Inline newRun = new Run();
    foreach (string noteAttStr in nodeAttList) //with this we can set all the attributes to the inline
    {
        switch (noteAttStr)
        {
            case ("b"):
            case ("strong"):
                {
                    newRun.FontWeight = FontWeights.Bold;
                    break;
                }
            case ("i"):
            case ("em"):
                {
                    newRun.FontStyle = FontStyle.Italic;
                    break;
                }
        }
    }

    if(htmlNodeName == "#text") //the #text means that its a text node. Like <i><#text/></i>. Thanks @HungCao
    {
        ((Run)newRun).Text = htmlNode.InnerText;
    } else //if it is not a #text, don't load its innertext, as it's another node and it will always have a #text node as a child (if it has any text)
    {
        foreach (HtmlNode childNode in htmlNode.ChildNodes)
        {
            InterNode(childNode, ref originalPar);
        }
    }

    return true;
}

Remarque: je sais que j'ai dit que mon application devait restituer le code HTML de la même manière qu'une webview, et je sais que cet exemple de code génère la même chose qu'une webview, mais comme je l'ai dit précédemment, il s'agit simplement d'une légère version de mon code final. En fait, mon code original / complet fonctionne comme il me faut et il ne s'agit que de la base.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi