htmlagilitypack使用2个htmldocument对象时的奇怪行为

时间:2012-06-16 12:31:58

标签: object html-agility-pack dom selectsinglenode

以下是代码:

HtmlDocument htmlDoc = new HtmlDocument();
HtmlDocument segment = new HtmlDocument();

htmlDoc.OptionWriteEmptyNodes = true;
segment.OptionWriteEmptyNodes = true;            

htmlDoc.Load("sourcepath");
segment.Load("sourcepath");

//Fix HtmlAgilityPack bug with ending tag at xmldeclaration
var newNodeStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
var newNode = HtmlNode.CreateNode(newNodeStr);
htmlDoc.DocumentNode.ReplaceChild(newNode, htmlDoc.DocumentNode.FirstChild);
segment.DocumentNode.ReplaceChild(newNode, segment.DocumentNode.FirstChild);    

HtmlNode sbodyNode = segment.DocumentNode.SelectSingleNode("//body");
if (sbodyNode != null)
sbodyNode.RemoveAllChildren();

HtmlNode bodyNode = htmlDoc.DocumentNode.SelectSingleNode("//body");
int numberOfChilds = bodyNode.ChildNodes.Count;
MessageBox.Show(numberOfChilds.ToString());

segment.Save("destpath1", Encoding.UTF8);
htmlDoc.Save("destpath2", Encoding.UTF8);

输入很简单xhtml。我想修改一个xhtml文件(这由htmlDoc表示)。为此,我创建了另一个HtmlDocument对象(段,将相同的xhtml加载到其中)。作为第一步,我试图剥夺身体元素的所有孩子。然后我将使用htmlDoc obeject添加一些元素。上面的问题是从段中删除这些也会影响htmlDoc(另一个对象)。因此MessageBox将始终显示0。除此之外,如果我看一下由Save函数产生的输出,htmlDoc下面会有元素,这意味着MessageBox应该显示它们的数量(据我所知)。(注意:如果我取消注释RemoveAllChildren()行,然后MessageBox显示正确的数字。) 我认为这是一些微不足道的东西,但对我来说有点奇怪。谢谢你的帮助。

更新:抱歉,我没有发布完整的代码,因为我认为有些行无关紧要,但看起来并非如此。如果我在Loads之后注释掉那4行,我会得到正确的数字并且它会像预期的那样工作。问题是为什么这些线会“伤害”。 (我写这些行来修复输出,因为agilitypack使xml标题结束标记/&gt;而不是?&gt;)

3 个答案:

答案 0 :(得分:0)

以下解决了我的问题,但不确定原因。如果有人想解释我会很高兴。

var newNodeStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
var newNode = HtmlNode.CreateNode(newNodeStr);
var newNode2 = HtmlNode.CreateNode(newNodeStr);
htmlDoc.DocumentNode.ReplaceChild(newNode, htmlDoc.DocumentNode.FirstChild);
segment.DocumentNode.ReplaceChild(newNode2, segment.DocumentNode.FirstChild);

答案 1 :(得分:0)

这实际上很合乎逻辑。 ReplaceChild不克隆子节点,它只是插入引用。因此,如果您在其上调用ClearChildNodes(),它将在添加引用的所有文档中清除。看起来HtmlNode实现了CloneNode,CopyTo和Clone。应该调用其中一种方法将节点的副本插入到每个文档中。

var newNodeStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
var newNode = HtmlNode.CreateNode(newNodeStr);

htmlDoc.DocumentNode.ReplaceChild(newNode.CloneNode(true), htmlDoc.DocumentNode.FirstChild);
segment.DocumentNode.ReplaceChild(newNode.CloneNode(true), segment.DocumentNode.FirstChild);

答案 2 :(得分:0)

当您使用&#34; watch&#34;添加或删除或替换元素时,HtmlAgilityPack有一个错误。并且您正在调试...以修复这种奇怪的行为,在调试模式下清除您的监视列表...