我是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:00
,00:00:29
和I'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;
}
}
我在变量a
,b
和c
中获取值。但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:00
,00:00:29
和I'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
答案 0 :(得分:6)
您希望使用XML解析器解析HTML。这也可能是您获得This document already has a 'DocumentElement' node.
异常的原因:因为您有多个根节点,在HTML中允许(或更好:容忍),而不是XML。
改为使用HTML解析器。遗憾的是,.NET框架中没有任何内置功能。你必须为此采取第三方库。一个非常好的是HTML agility pack,oleksii在他的评论中已经提到过。
修改强>
从您的评论中,我感觉您不熟悉HTML和XML之间没有直接关系的事实。从here获取的图形很好地说明了这一点:
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表示。