Анализ ошибок в гибкой манере HTMl и возврат XElement

.net-3.5 c# html-agility-pack html-parsing

Вопрос

Я могу анализировать документ и генерировать вывод, однако вывод не может быть проанализирован в XElement из-за тега ap, все остальное в строке правильно разбирается.

Мой ввод:

var input = "<p> Not sure why is is null for some wierd reason!<br><br>I have implemented the auto save feature, but does it really work after 100s?<br></p> <p> <i>Autosave?? </i> </p> <p>we are talking...</p><p></p><hr><p><br class=\"GENTICS_ephemera\"></p>";

Мой код:

public static XElement CleanupHtml(string input)
    {  


    HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();

    htmlDoc.OptionOutputAsXml = true;
    //htmlDoc.OptionWriteEmptyNodes = true;             
    //htmlDoc.OptionAutoCloseOnEnd = true;
    htmlDoc.OptionFixNestedTags = true;

    htmlDoc.LoadHtml(input);

    // ParseErrors is an ArrayList containing any errors from the Load statement
    if (htmlDoc.ParseErrors != null && htmlDoc.ParseErrors.Count() > 0)
    {

    }
    else
    {

        if (htmlDoc.DocumentNode != null)
        {
            var ndoc = new HtmlDocument(); // HTML doc instance
            HtmlNode p = ndoc.CreateElement("body");  

            p.InnerHtml = htmlDoc.DocumentNode.InnerHtml;
            var result = p.OuterHtml.Replace("<br>", "<br/>");
            result = result.Replace("<br class=\"special_class\">", "<br/>");
            result = result.Replace("<hr>", "<hr/>");
            return XElement.Parse(result, LoadOptions.PreserveWhitespace);
        }
    }
    return new XElement("body");

}

Мой выход:

<body>
   <p> Not sure why is is null for some wierd reason chappy!
   <br/>
   <br/>I have implemented the auto save feature, but does it really work after 100s?
   <br/>
   </p> 
   <p> 
   <i>Autosave?? </i> 
   </p> 
   <p>we are talking...</p>
   **<p>**
   <hr/>
   <p>
   <br/>
   </p>
</body>

Полужирный тэг тег, который не выводил правильно ... Есть ли способ обойти это? Я что-то не так с кодом?

Принятый ответ

То, что вы пытаетесь сделать, в основном преобразует вход Html в вывод Xml.

Html Agility Pack может это сделать, если вы используете опцию OptionOutputAsXml , но в этом случае вы не должны использовать свойство InnerHtml, а вместо этого использовать Html Agility Pack для работы с вами, используя один из методов Save HtmlDocument.

Вот общая функция для преобразования HTML-текста в экземпляр XElement:

public static XElement HtmlToXElement(string html)
{
    if (html == null)
        throw new ArgumentNullException("html");

    HtmlDocument doc = new HtmlDocument();
    doc.OptionOutputAsXml = true;
    doc.LoadHtml(html);
    using (StringWriter writer = new StringWriter())
    {
        doc.Save(writer);
        using (StringReader reader = new StringReader(writer.ToString()))
        {
            return XElement.Load(reader);
        }
    }
}

Как вы видите, вам не нужно много работать самостоятельно! Обратите внимание, что поскольку ваш исходный текст ввода не имеет корневого элемента, Html Agility Pack автоматически добавит один закрытый SPAN чтобы гарантировать, что вывод действителен Xml.

В вашем случае вы хотите дополнительно обработать некоторые теги, так что вот как это сделать с вашим примером:

    public static XElement CleanupHtml(string input)
    {
        if (input == null)
            throw new ArgumentNullException("input");

        HtmlDocument doc = new HtmlDocument();
        doc.OptionOutputAsXml = true;
        doc.LoadHtml(input);

        // extra processing, remove some attributes using DOM
        HtmlNodeCollection coll = doc.DocumentNode.SelectNodes("//br[@class='special_class']");
        if (coll != null)
        {
            foreach (HtmlNode node in coll)
            {
                node.Attributes.Remove("class");
            }
        }

        using (StringWriter writer = new StringWriter())
        {
            doc.Save(writer);
            using (StringReader reader = new StringReader(writer.ToString()))
            {
                return XElement.Load(reader);
            }
        }
    }

Как вы видите, вы не должны использовать функцию raw string, но вместо этого используйте функции DOM Html Agility Pack (SelectNodes, Add, Remove и т. Д.).


Популярные ответы

Если вы проверите комментарии к документации для OptionFixNestedTags вы увидите следующее:

//     Defines if LI, TR, TH, TD tags must be partially fixed when nesting errors
//     are detected. Default is false.

Так что я не думаю , что это поможет вам с незамкнутыми HTML p тегов. Согласно старой библиотеке запросов SO C для очистки html, хотя HTML Tidy может работать для этой цели.



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow