HtmlAgility编辑foreach

时间:2016-03-21 20:20:19

标签: c# html-agility-pack

我尝试使用一些已编辑的HTML替换我的根文档中的某些节点,但我收到错误:Collection was modified; perhaps enumeration operation is not performed. on parallel foreach。我知道发生此错误是因为我正在修改循环内的原始结构。我怎么能这样做?我可以使用Parallel.ForEach,还是只能使用普通foreach

这是我的代码:

Parallel.ForEach( blocks, block =>
{
    var HtmlBlockDoc = new HtmlDocument();

    HtmlBlockDoc.LoadHtml( block.Html );

    var Node = HtmlDoc.DocumentNode.Descendants().FirstOrDefault( x => x.StreamPosition == block.Order );

    if( Node != null )
        Node.ParentNode.ReplaceChild( HtmlBlockDoc.DocumentNode, Node );
});

块var包含一些属性,但主要属性是Html,这是我要在HtmlDoc.DocumentNodeOrder StreamPosition that he currently is上替换的html。我没有删除或添加新节点,我只是将<div></div>替换为<div><p>My Parsed HTML</p></div>。我使用HtmlAgilityPack来操纵HTML。

我也尝试克隆HtmlDoc.DocumentNode,但我得到了同样的错误。

修改

我试图使用另一种方法来检索和替换所需的节点来解决此问题。如果我尝试使用HtmlDoc.DocumentNode.Descendants(),我的搜索将在第一次替换后失败,因为它将更改原始结构。

怎么样?好吧,在Descendants方法中,我得到所有Child Nodes以及他们的Grand Childs Nodes,好像它们处于同一级别一样,所以如果我在第一次替换时使用任何位置标识符,它将起作用,在第二次更换时,它不会因为我添加了更多节点而且这些节点也将被添加到Descendants的{​​{1}}列表中。

在发现我看到我可以使用ChildNodes之后,它将遵循三者的真实结构。要做到这一点,我将得到每个孩子,寻找我的节点和:

  • 如果我找到了:替换并继续使用foreach;
  • 如果我找不到它:获取下一个子节点或获得下一个兄弟节点并查看他的孩子的节点

我知道我需要使用递归函数来实现这一点,但我在如何做到这一点时遇到了一些问题。这是我修改过的代码:

DocumentNode

如果有人想要重新创建问题,我在此处发布了原始HTML:PasteBin

0 个答案:

没有答案