HTMl 敏捷包错误解析并返回 XElement

Posted

技术标签:

【中文标题】HTMl 敏捷包错误解析并返回 XElement【英文标题】:HTMl agility pack error parsing and returning XElement 【发布时间】:2011-07-17 13:19:31 【问题描述】:

我可以解析文档并生成输出,但是由于 p 标记,输出无法解析为 XElement,字符串中的其他所有内容均已正确解析。

我的意见:

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>

粗体 p 标签是没有正确输出的标签...有没有办法解决这个问题?我的代码有问题吗?

【问题讨论】:

【参考方案1】:

您要做的基本上是将 Html 输入转换为 Xml 输出。

当您使用 OptionOutputAsXml 选项时,Html Agility Pack 可以做到这一点,但在这种情况下,您不应该使用 InnerHtml 属性,而是让 Html Agility Pack 为您完成基础工作,使用 HtmlDocument 的 @ 之一987654322@ 方法。

这是一个将 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);
            
        
    

如您所见,您不应使用原始字符串函数,而应使用 Html Agility Pack DOM 函数(SelectNodes、Add、Remove 等...)。

【讨论】:

这行得通,很奇怪为什么我必须保存才能获得正确的输出,无论如何 - 我将如何处理 nbsp;如果它包含在输入中?你会推荐我使用 anti.xss 库吗? +1 我什至不知道OptionOutputAsXml(及其用例) HtmlAgilityPack 的转换似乎不是特别可靠,例如我收到此错误:6XmlException '',十六进制值 0x03,是无效字符。第 2081 行,位置 822。 LineNumber 2081 LinePosition 822 如果是新问题,请发布新问题。【参考方案2】:

如果您查看 OptionFixNestedTags 的文档 cmets,您将看到以下内容:

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

所以我认为这不会帮助您处理未封闭的 HTML p 标签。根据一个旧的 SO 问题 C# library to clean up html 尽管 HTML Tidy 可能适用于此目的。

【讨论】:

感谢您的信息...我输入的问题是我有一个有效的

标签,但它没有被正确处理,它们只是空元素!

变成

以上是关于HTMl 敏捷包错误解析并返回 XElement的主要内容,如果未能解决你的问题,请参考以下文章

HTML 敏捷包

HTML 敏捷包:解析 href 标签

Xpath 使用 html 敏捷包返回 null

C# Html 敏捷包 ( SelectSingleNode )

在解析期间设置命名空间

如何在 Html 敏捷包中删除基于 id 和 value 的输入