C# HtmlAgility编辑foreach内部的HtmlNode

C# HtmlAgility编辑foreach内部的HtmlNode,c#,html-agility-pack,C#,Html Agility Pack,我试图用一些经过编辑的HTML替换根文档中的一些节点,但我得到一个错误:集合被修改;可能未执行枚举操作。在并行foreach上。我知道发生此错误是因为我正在修改循环中的原始结构。我怎么做呢?我可以使用Parallel.ForEach吗?或者我只能使用普通的ForEach 这是我的代码: Parallel.ForEach( blocks, block => { var HtmlBlockDoc = new HtmlDocument(); HtmlBlockDoc.LoadH

我试图用一些经过编辑的HTML替换根文档中的一些节点,但我得到一个错误:
集合被修改;可能未执行枚举操作。在并行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 );
});
block var包含一些属性,但主要的属性是
Html
,这是我要在
HtmlDoc.DocumentNode
上替换的Html,而
Order
是他当前所在的
流位置。我没有删除或添加新节点,我只是用我解析的HTML替换了一个
。我正在使用它来操作HTML

我还试图克隆
HtmlDoc.DocumentNode
,但我得到了相同的错误

编辑

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

怎么做?好的,在
子节点
方法中,我得到所有
子节点
以及它们的
孙子节点
,就好像它们处于同一级别,因此如果我在第一次替换时使用任何位置标识符,它都会起作用,在第二次替换中,它不会,因为我添加了更多节点,这些节点也将添加到
DocumentNode
子体列表中

在发现我可以使用ChildNodes之后,因为它将遵循三个节点的真实结构。为此,我必须获取每个子节点,查找我的节点并:

  • 如果我找到了:替换并继续使用foreach
  • 如果我找不到:获取下一个子节点,或者获取下一个兄弟节点,在他的子节点中查找我的节点
我知道我需要使用递归函数来实现这一点,但我在如何实现这一点上遇到了一些问题。这是我修改过的代码:

var HtmlDoc = new HtmlDocument { OptionFixNestedTags = true };
HtmlDoc.LoadHtml( "My HTML" );

foreach( var block in blocks )
{
    var HtmlBlockDoc = new HtmlDocument();

    HtmlBlockDoc.LoadHtml( block.Html.CleanHTML( false ).ReplaceWhiteSpaceTags() );

    ReplaceHtmlNode( HtmlDoc, block );
}

private static List<HtmlNode> ReplaceHtmlNode( HtmlDocument htmlDoc, TemplateBlock block )
{
    var Node = htmlDoc.DocumentNode.ChildNodes.FirstOrDefault( x => x.XPath.Equals( block.XPath ) );

    if( Node != null )
        Node.ParentNode.ReplaceChild( htmlDoc.DocumentNode, Node );
    else
    {
        //How to do it and how to know when to leave ?
        ReplaceHtmlNode(  )
    }
}
var HtmlDoc=new HtmlDocument{OptionFixNestedTags=true};
HtmlDoc.LoadHtml(“我的HTML”);
foreach(块中的var块)
{
var HtmlBlockDoc=新的HtmlDocument();
HtmlBlockDoc.LoadHtml(block.Html.CleanHTML(false.ReplaceWhiteSpaceTags());
替换HTMLNODE(HtmlDoc,块);
}
私有静态列表替换HtmlNode(HtmlDocument htmlDoc、TemplateBlock)
{
var Node=htmlDoc.DocumentNode.ChildNodes.FirstOrDefault(x=>x.XPath.Equals(block.XPath));
如果(节点!=null)
Node.ParentNode.ReplaceChild(htmlDoc.DocumentNode,Node);
其他的
{
//怎么做,怎么知道什么时候离开?
替换HtmlNode()
}
}

我在这里发布了我的原始HTML,如果有人想让它重现这个问题:

我很确定你的
无论什么
都会在文档中添加一个新节点。“普通”foreach
也会给你同样的错误。@JimMischel,如果我用普通foreach也会出现同样的错误,我怎么解决这个问题呢?你总是可以为修改过的节点创建一个新列表。我试着这么做,克隆了根节点并在foreach中使用它们,但是他们不会复制我用来查找要替换的节点的StreamPosition。有什么想法吗?它与使用
foreach
的任何其他构造没有什么不同,您正在修改
foreach
语句体中枚举的内容。你不能那样做。