Comment réparer le HTML mal formé avec HTML Agility Pack?

.net c# html html-agility-pack parsing

Question

J'ai ce code HTML mal formé avec des balises qui se chevauchent:

<p>word1<b>word2</p>
<p>word3</b>word4</p>

Le chevauchement peut également être imbriqué.

Comment puis-je le convertir en HTML bien formé avec HTML Agility Pack (HAP)?

Je cherche cette sortie:

<p>word1<b>word2</b></p>
<p><b>word3</b>word4</p>

J'ai essayé HtmlNode.ElementsFlags["b"] = HtmlElementFlag.Closed | HtmlElementFlag.CanOverlap , mais cela ne fonctionne pas comme prévu.

Réponse acceptée

Il est dans le travail de fait comme prévu, mais peut - être ne fonctionne pas comme prévu. Quoi qu'il en soit, voici un exemple de code (une application console) qui montre comment vous pouvez effectuer des corrections HTML à l'aide de la bibliothèque.

La bibliothèque possède une collection ParseErrors que vous pouvez utiliser pour déterminer quelles erreurs ont été détectées lors de l'analyse syntaxique du balisage.

Il y a vraiment deux types de problèmes ici:

1) éléments non fermés . Celui-ci est corrigé par défaut par la bibliothèque, mais une option sur l'élément P l'empêche dans ce cas.

2) éléments non ouverts . Celui-ci est plus complexe, car cela dépend de la manière dont vous voulez résoudre le problème. Où voulez-vous que la balise soit ouverte? Dans l'exemple suivant, j'ai utilisé le noeud frère précédent le plus proche pour ouvrir l'élément.

static void Main(string[] args)
{
    // clear the flags on P so unclosed elements in P will be auto closed.
    HtmlNode.ElementsFlags.Remove("p");

    // load the document
    HtmlDocument doc = new HtmlDocument();
    doc.Load("yourTestFile.htm");

    // build a list of nodes ordered by stream position
    NodePositions pos = new NodePositions(doc);

    // browse all tags detected as not opened
    foreach (HtmlParseError error in doc.ParseErrors.Where(e => e.Code == HtmlParseErrorCode.TagNotOpened))
    {
        // find the text node just before this error
        HtmlTextNode last = pos.Nodes.OfType<HtmlTextNode>().LastOrDefault(n => n.StreamPosition < error.StreamPosition);
        if (last != null)
        {
            // fix the text; reintroduce the broken tag
            last.Text = error.SourceText.Replace("/", "") + last.Text + error.SourceText;
        }
    }

    doc.Save(Console.Out);
}

public class NodePositions
{
    public NodePositions(HtmlDocument doc)
    {
        AddNode(doc.DocumentNode);
        Nodes.Sort(new NodePositionComparer());
    }

    private void AddNode(HtmlNode node)
    {
        Nodes.Add(node);
        foreach (HtmlNode child in node.ChildNodes)
        {
            AddNode(child);
        }
    }

    private class NodePositionComparer : IComparer<HtmlNode>
    {
        public int Compare(HtmlNode x, HtmlNode y)
        {
            return x.StreamPosition.CompareTo(y.StreamPosition);
        }
    }

    public List<HtmlNode> Nodes = new List<HtmlNode>();
}


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow