HTML Agility Pack移除换行标签闭合。

17

我正在使用 HTML Agility Pack 创建一个 HTML 文档。我加载一个模板文件,然后将内容附加到它上面。这些都有效,但是当我查看输出文件时,它已经删除了我的 <br/> 标签的闭合标签,变成了这样的 <br>。是什么原因导致这种情况发生?

Dim doc As New HtmlDocument()
doc.Load(Server.MapPath("Template.htm"))

Dim title As HtmlNode = doc.DocumentNode.SelectSingleNode("//title")

title.InnerHtml = title.InnerHtml & "CEU Classes"
Dim topContent As HtmlAgilityPack.HtmlNode = doc.GetElementbyId("topContent")

topContent.InnerHtml = html.ToString
doc.OptionWriteEmptyNodes = True
doc.Save(outputFileName, Encoding.UTF8)

更多信息:

在我添加了doc.OptionWriteEmptyNodes = True之后,它删除了我的闭合图像标签,现在不再这样做了。

更新

这是我现在的代码,它删除了闭合的BR标签。

Dim html As String = "Words<br/>more words"
Dim doc As New HtmlDocument()
Dim title As HtmlNode
Dim topContent As HtmlNode

HtmlNode.ElementsFlags("br") = HtmlElementFlag.Empty
doc.Load(Server.MapPath("Template.htm"))

Title = doc.DocumentNode.SelectSingleNode("//title")
title.InnerHtml = title.InnerHtml & "CEU Classes"

topContent = doc.GetElementbyId("topContent")
topContent.InnerHtml = html.ToString

doc.OptionWriteEmptyNodes = True
doc.Save(outputFileName, Encoding.UTF8)

更新2

最终我只是将模板文件读入为一个标准字符串,然后像这样加载HTML。

Dim TemplateHTML As String = File.ReadAllText(Server.MapPath("Template.htm"))

TemplateHTML = TemplateHTML.Insert(TemplateHTML.IndexOf("<div id=""topContent"">") + "<div id=""topContent"">".Length, _
                                   html.ToString)

doc.LoadHtml(TemplateHTML)
4个回答

21

这是因为 Html Agility Pack 以一种特殊的方式处理BR。它仍然支持旧版(但今天在Web上存在的)HTML 3.2语法,其中BR可以完全没有结束标记声明(顺便说一下,浏览器也能很好地处理它...)。

要更改此默认行为,您需要修改 HtmlNode.ElementFlags 属性,像这样:

Dim doc As New HtmlDocument()
HtmlNode.ElementsFlags("br") = HtmlElementFlag.Empty
doc.LoadHtml("<test>before<br/>after</test>")
doc.OptionWriteEmptyNodes = True   
doc.Save(Console.Out)

它将显示:

<test>before<br />after</test>

我添加了你建议的代码,但它仍然剥离了斜杠。 - FarFigNewton
@guanome - 我已更新我的答案。此代码已使用Html Agility Pack 1.3进行测试。 - Simon Mourier
我放进Template.htm的任何内容都会看起来正确,也就是说<br/>标签是完整的。问题在于topcontent部分中的任何<br/>标签都没有结束标记。我该如何解决这个问题?topContent = doc.GetElementbyId("topContent") topContent.InnerHtml = html.ToString - FarFigNewton

7
根据@Simon Mourier的说法,以下C#代码适用于1.4版本。
var doc = new HtmlDocument();
HtmlNode.ElementsFlags["br"] = HtmlElementFlag.Empty;
doc.OptionWriteEmptyNodes = true;
doc.LoadHtml("Lorem ipsum dolor sit<br/>Lorem ipsum dolor sit");

var postParsed = doc.DocumentNode.WriteTo();

postParsed的字符串值如下

"Lorem ipsum dolor sit<br />Lorem ipsum dolor sit"

1
无论我放什么到Template.htm中,都会正确显示,也就是说 <br/> 标签保持完好无损。问题在于 topcontent 部分的任何 <br/> 标签都没有闭合标签。我该如何修复它?topContent = doc.GetElementbyId("topContent") topContent.InnerHtml = html.ToString - FarFigNewton
1
我遇到了同样的问题,但是针对 <img /> 标签。这解决了我的问题。 - Scott Miller

2

看起来这是Html Agility Pack中的一个标准设置。默认情况下,它不符合XHTML规范,许多标签没有关闭。

有两种方法可以解决这个问题。在文档级别上,您可以执行以下操作,打开所有关闭标签(这是我首选的方法)。

HtmlDocument doc = new HtmlDocument();
doc.OptionWriteEmptyNodes = true;
doc.LoadHtml(content);

然而,这可能并不是理想的方法。在节点级别有另一种方法可以实现。

if (HtmlNode.ElementsFlags.ContainsKey("img"))
{
    HtmlNode.ElementsFlags["img"] = HtmlElementFlag.Closed;
}
else
{
    HtmlNode.ElementsFlags.Add("img", HtmlElementFlag.Closed);
}

1

我曾经遇到过同样的问题,我通过使用新的HtmlDocument对象手动重新解析HTML块并使用正确的设置来解决它。

我认为问题在于HtmlDocument具有让您关闭
标签等的所有漂亮设置,但是当您选择节点或执行某些其他类型的节点操作并使用其OuterHtml或InnerHtml时,一些关闭标签会丢失(可能是因为这些属性不使用与文档本身相同的设置,或者可能有其他原因)。因此,当您从InnerHtml或OuterHtml获取不正确的html字符串时,您可以再次使用HtmlDocument进行重新解析,并使用document.DocumentElement.InnerHtml获取正确的HTML字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接