Странное поведение htmlagilitypack при использовании 2 объектов htmldocument

Вот код:

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 в него). В качестве первого шага я пытаюсь лишить всех детей элемента body. Затем я бы добавил некоторые элементы обратно, используя объект htmlDoc. Проблема с вышеупомянутым состоит в том, что удаление их из сегмента также влияет на htmlDoc (другой объект). Таким образом, MessageBox всегда будет показывать 0. Вдобавок к этому, если я посмотрю на выходные данные, которые создаются функциями Save, htmlDoc будет иметь элементы под, что будет означать, что MessageBox должен показывать их количество (насколько я думаю). (Примечание: если я раскомментирую строку RemoveAllChildren(), затем MessageBox показывает правильное число.) Я думаю, что это несколько тривиальные вещи, но это немного странно для меня. Спасибо за вашу помощь.

Обновление: Извините, я не опубликовал полный код, потому что я думал, что некоторые строки не имеют значения, но похоже, что это не так. Если я закомментирую эти 4 строки после загрузок, я получу правильные числа, и это будет работать, как и ожидалось. Вопрос в том, почему эти строки "вредят". (эти строки я написал, чтобы исправить вывод, потому что agilitypack сделал закрывающий тег заголовка xml /> вместо?>)

3 ответа

Следующее решает мою проблему, но не уверен почему. Если кто-нибудь захочет объяснить, я был бы признателен.

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);

HtmlAgilityPack имеет ошибку, когда вы добавляете, удаляете или заменяете элементы, когда вы используете "watch" и вы отлаживаете... чтобы исправить это странное поведение, очистите ваш список наблюдения в режиме отладки...

Это на самом деле вполне логично. 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);
Другие вопросы по тегам