从HTML节点读取值

时间:2012-06-30 20:20:06

标签: c# html html-parsing

我是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

2 个答案:

答案 0 :(得分:6)

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

改为使用HTML解析器。遗憾的是,.NET框架中没有任何内置功能。你必须为此采取第三方库。一个非常好的是HTML agility pack,oleksii在他的评论中已经提到过。

修改

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

Relation between SGML, HTML and XML

XML既不是HTML的子集,也不是相反的方式。只有你有严格的XHTML(很少这种情况),你才有一个可以用XML解析器解析的HTML文档。但请注意,如果此类XHTML文档的代码中存在某些错误,则解析器将失败,而常见的浏览器将继续显示该页面。此外,XHTML的未来还不太清楚,现在HTML5正在缓慢但稳定地生活......

总结一下:为了避免所有这些陷阱,请采取简单的方法去寻找HTML解析器。

答案 1 :(得分:3)

由于您要解析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中,而且非常困难 - 修复未关闭的标记(例如&lt; BR&gt;),在属性周围加上引号,给出没有值的属性值等等。因为我想要使用在加载到HTML DOM并在其中导航之后,针对它的XSLT为每个HTML节点创建相关的XML节点。然后我有一个正确的HTML表示。