【问题标题】:Read value from HTML node从 HTML 节点读取值
【发布时间】:2012-07-01 21:44:06
【问题描述】:

我是 XML/HTML 解析的新手。甚至不知道正确搜索重复项的正确词。

我有一个如下所示的 HTML 文件:

<body id="s1" style="s1">
    <div xml:lang="uk">
        <p begin="00:00:00" end="00:00:29">
          <span fontFamily="SchoolHouse Cursive B" fontSize="18">I'm great!</span>
        </p>

现在我需要 00:00:0000:00:29I'm great!。我可以这样读:

XmlTextReader reader = new XmlTextReader(file);
while (reader.Read())
{
    if (reader.NodeType != XmlNodeType.Element)
        continue;

    if (reader.LocalName != "p")
        continue;

    var a = reader.GetAttribute(0);
    var b = reader.GetAttribute(1);

    if (reader.LocalName == "span")
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(reader);
        XmlNode elem = doc.DocumentElement.FirstChild;
        var c = elem.InnerText;
    }
 }

我在变量 abc 中获取值。但 HTML 格式略有变化。 现在 HTML 看起来像这样:

<body id="s1" style="s1">
  <div xml:lang="uk">
      <p begin="00:00:00" end="00:00:29">I'm great! </p>

在这种情况下,我如何解析出 00:00:0000:00:29I'm great! ?我试过这个:

XmlTextReader reader = new XmlTextReader(file);
while (reader.Read())
{
    if (reader.NodeType != XmlNodeType.Element)
        continue;

    if (reader.LocalName != "p")
        continue;

    var a = reader.GetAttribute(0);
    var b = reader.GetAttribute(1);

    XmlDocument doc = new XmlDocument();
    doc.Load(reader);
    XmlNode elem = doc.DocumentElement.FirstChild;
    var c = elem.InnerText;
}

但我得到了这个错误:This document already has a 'DocumentElement' node.doc.Load(reader) 行。如何正确阅读以及造成问题的原因是什么?我正在使用 .NET 2.0

【问题讨论】:

  • 看看html agility pack,好像是需要解析html的。
  • @oleksii 当 System.Xml 下有很多库时,我真的应该使用第三方库吗?此外,我没有做任何与 html 相关的事情
  • 很明显,XML != HTML,我认为如果您进行任何 html 解析,html 敏捷包将很有用,因为您似乎在示例中有一些 html。如果您不使用 html,那么不妨看看 LINQ-to-XML。
  • @oleksii:我的意思是操作,而不是你 :) 我基本上只是确认了你所说的。
  • 有人可以相应地编辑问题的标题吗?我不太确定这个 XML 什么时候听起来像 HTML

标签: c# html html-parsing


【解决方案1】:

看起来您有想要使用 XML 解析器解析的 HTML。这也可能是您得到 This document already has a 'DocumentElement' node. 异常的原因:因为您有多个根节点,这在 HTML 中是允许的(或者更好的是:容忍),但在 XML 中是不允许的。

改用 HTML 解析器。不幸的是,.NET 框架中没有内置任何内容。您必须为此使用第三方库。一个很好的是HTML agility pack,oleksii 在他的评论中已经提到了。

编辑:

从您的 cmets 中,我感觉您不熟悉 HTML 和 XML 之间没有直接关系这一事实。取自here 的图很好地说明了这一点:

XML 也不是 HTML 的子集,反之亦然。只有当您有严格的 XHTML(很少出现这种情况)时,您才有可以用 XML 解析器解析的 HTML 文档。但请注意,如果此类 XHTML 文档的代码出现错误,解析器将失败,而普通浏览器将继续显示该页面。此外,XHTML 的未来还很不明朗,现在 HTML5 正在缓慢而稳定地出现......

总结一下:为了避免所有这些陷阱,走简单的路,使用 HTML 解析器。

【讨论】:

  • 使用 .NET XML 类无法解析?
  • 不,很遗憾没有。 HTML 不是 XML 的子集。此外,由于 HTML 解析器(也用于浏览器中的解析器)在解析无效输入时更加宽容,人们开始为网站编写无效的 HTML,或者只是不关心有效性。但是,XML 解析器期望 严格有效 输入,如果不是,它们会退出解析并抛出异常,就像您看到的那样。
  • 你能相应地编辑问题的标题吗?我不太确定这个 XML 什么时候听起来像 HTML
  • @nawfal:编辑标题并更正您问题的标签
【解决方案2】:

由于您想要解析 HTML,您可以使用WebClient(或WebBrowser)加载页面,然后使用 HTML DOM 浏览它。您需要为以下代码示例添加对Microsoft HTML Object Library (COM) 的引用:

  string html;
  WebClient webClient = new WebClient();
  using (Stream stream = webClient.OpenRead(new Uri("http://www.google.com")))
  using (StreamReader reader = new StreamReader(stream))
  {
    html = reader.ReadToEnd();
  }
  IHTMLDocument2 doc = (IHTMLDocument2)new HTMLDocument();
  doc.write(html);
  foreach (IHTMLElement el in doc.all)
    Console.WriteLine(el.tagName);

我之前尝试过将 HTML 加载到 XML 中,但这太难了 - 修复未封闭的标签(如
),在属性周围加上引号,给没有值的属性一个值,等等。因为我想然后使用 XSLT针对它,在加载到 HTML DOM 并在其中导航后,为每个 HTML 节点创建相关的 XML 节点。然后我有了 HTML 的正确 XML 表示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多