【问题标题】:How to read HTML as XML?如何将 HTML 读取为 XML?
【发布时间】:2011-07-25 05:40:34
【问题描述】:

我想从从 Internet 下载的 html 页面中提取几个链接,我认为使用 linq to XML 对我的情况来说是一个很好的解决方案。
我的问题是我无法从 HTML 创建 XmlDocument,使用 Load(string url) 不起作用,所以我使用以下方法将 html 下载到字符串:

public static string readHTML(string url)
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse res = (HttpWebResponse)req.GetResponse();
        StreamReader sr = new StreamReader(res.GetResponseStream());

        string html = sr.ReadToEnd();
        sr.Close();
        return html;
    }

当我尝试使用 LoadXml(string xml) 加载该字符串时,出现异常

'--' is an unexpected token. The expected token is '>'

我应该采取什么方式将 html 文件读取为可解析的 XML

【问题讨论】:

  • HTML 不一定是有效的 XML。 HTML 基于 SGML,它本身是 XML 的超集(一种)。因此,您需要一个特殊的 HTML 解析器,而不是通用的 XML 解析器。
  • 更多相同的答案和上面的评论。 HTML 不是 XML

标签: c# html xml html-parsing


【解决方案1】:

HTML 与 XML 完全不同(除非 HTML 实际上恰好符合 XML 模式下的 XHTML 或 HTML5)。最好的方法是使用HTML parser 来阅读 HTML。之后您可以将其转换为 Linq to XML - 或直接对其进行处理。

【讨论】:

    【解决方案2】:

    我自己没用过,不过建议你看看SGMLReader。以下是他们主页上的示例:

    XmlDocument FromHtml(TextReader reader) {
    
        // setup SgmlReader
        Sgml.SgmlReader sgmlReader = new Sgml.SgmlReader();
        sgmlReader.DocType = "HTML";
        sgmlReader.WhitespaceHandling = WhitespaceHandling.All;
        sgmlReader.CaseFolding = Sgml.CaseFolding.ToLower;
        sgmlReader.InputStream = reader;
    
        // create document
        XmlDocument doc = new XmlDocument();
        doc.PreserveWhitespace = true;
        doc.XmlResolver = null;
        doc.Load(sgmlReader);
        return doc;
    }
    

    【讨论】:

    • +1 我使用 SGMLReader 已经很多年了(自从它被引入以来)。它非常健壮,可以处理一些非常糟糕的畸形 HTML。
    【解决方案3】:

    如您所述,如果您想从页面中提取一些链接,请尝试使用HTML Agility Pack

    此代码从网络获取一个页面并提取所有链接:

    HtmlWeb web = new HtmlWeb();  
    HtmlDocument document = web.Load("http://www.stackoverflow.com");  
    HtmlNode[] links = document.DocumentNode.SelectNodes("//a").ToArray(); 
    

    从磁盘打开一个 html 文件并获取特定链接的 URL:

    HtmlDocument document2 = new HtmlDocument();  
    document2.Load(@"C:\Temp\page.html")  
    HtmlNode link = document2.DocumentNode.SelectSingleNode("//a[@id='myLink']");
    Console.WriteLine(link.Attributes["href"].Value);
    

    【讨论】:

      【解决方案4】:

      HTML 不是 XML。 HTML 基于 SGML,因此不能确保标记是格式良好的 XML(XML 是 SGML 本身的子集)。您只能将 XHTML(即与 XML 兼容的 HTML)解析为 XML。当然,大多数网站并非如此。

      要使用 HTML,您需要使用 HTML 解析器。

      【讨论】:

      • 如果我可以标记两个答案,我会标记你的两个答案。
      【解决方案5】:

      如果您知道您感兴趣的节点,我会使用正则表达式从字符串中提取链接。

      【讨论】:

      • 正则表达式几乎从来都不是解析 HTML 或 XML 的明智方法
      • 我有想过,但我从来没有学过正则表达式,而且对于这么小的任务来说,学习它的主题太大了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-30
      • 2013-01-15
      • 2010-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多