Come risolvere l'HTML mal formato con HTML Agility Pack?

.net c# html html-agility-pack parsing

Domanda

Ho questo HTML malformato con tag sovrapposti:

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

Anche la sovrapposizione può essere annidata.

Come posso convertirlo in HTML ben formato con HTML Agility Pack (HAP)?

Sto cercando questo output:

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

Ho provato HtmlNode.ElementsFlags["b"] = HtmlElementFlag.Closed | HtmlElementFlag.CanOverlap , ma non funziona come previsto.

Risposta accettata

Si tratta infatti di lavoro come previsto, ma forse non funziona come previsto. Ad ogni modo, ecco un esempio di codice (un'applicazione Console) che dimostra come è possibile ottenere un po 'di correzione HTML usando la libreria.

La libreria ha una raccolta ParseErrors che è possibile utilizzare per determinare quali errori sono stati rilevati durante l'analisi del markup.

Ci sono davvero due tipi di problemi qui:

1) elementi non chiusi . Questo è fissato per impostazione predefinita dalla libreria, ma esiste un'opzione sull'elemento P che impedisce in questo caso.

2) elementi non aperti . Questo è più complesso, perché dipende da come lo vuoi risolvere, dove vuoi che il tag sia aperto? Nell'esempio seguente, ho utilizzato il nodo fratello più vicino di testo precedente per aprire l'elemento.

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



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é