C# 将节点与Html Agility Pack结合的最佳方法

C# 将节点与Html Agility Pack结合的最佳方法,c#,html-agility-pack,C#,Html Agility Pack,我已将一个大文档从Word转换为HTML。很接近,但我有一堆“代码”节点,我想将它们合并到一个“pre”节点中 以下是输入: <p>Here's a sample MVC Controller action:</p> <code> public ActionResult Index()</code> <code> {</code> <code> return Vi

我已将一个大文档从Word转换为HTML。很接近,但我有一堆“代码”节点,我想将它们合并到一个“pre”节点中

以下是输入:

<p>Here's a sample MVC Controller action:</p>
<code>        public ActionResult Index()</code>
<code>        {</code>
<code>            return View();</code>
<code>        }</code>
<p>We'll start by making the following changes...</p>
我想把它变成这样:

<p>Here's a sample MVC Controller action:</p>
<pre class="brush: csharp">        public ActionResult Index()
    {
        return View();
    }</pre>
<p>We'll start by making the following changes...</p>
通常我会删除第一个循环中的节点,但这在迭代过程中不起作用,因为在迭代集合时无法更改集合


更好的主意?

清理要解析的html

第一种方法:选择所有
节点,将它们分组,然后创建一个

var idx = 0;
var nodes = doc.DocumentNode
    .SelectNodes("//code")
    .GroupBy(n => new { 
        Parent = n.ParentNode, 
        Index = n.NextSiblingIsCode() ? idx : idx++ 
    });

foreach (var group in nodes)
{
    var pre = HtmlNode.CreateNode("<pre class='brush: csharp'></pre>");
    pre.AppendChild(doc.CreateTextNode(
        string.Join(Environment.NewLine, group.Select(g => g.InnerText))
    ));
    group.Key.Parent.InsertBefore(pre, group.First());

    foreach (var code in group)
        code.Remove();
}
它用于确定下一个同级节点是否为
节点。
第二种方法:只选择每个组顶部的
节点,然后遍历每个节点以查找下一个
节点,直到第一个非
节点。我在这里使用了
xpath

var nodes=doc.DocumentNode.SelectNodes(
“//代码[名称(前面的同级::*[1])!='code']
);
foreach(节点中的var节点)
{
var pre=HtmlNode.CreateNode(“”);
node.ParentNode.InsertBefore(pre,node);
var content=string.Empty;
var-next=node;
做
{
content+=next.InnerText+Environment.NewLine;
var previous=next;
next=next。选择SingleNode(“以下同级::*[1][name()='code']);
上一个。删除();
}while(next!=null);
pre.AppendChild(doc.CreateTextNode(
content.TrimEnd(Environment.NewLine.ToCharArray())
));
}
var idx = 0;
var nodes = doc.DocumentNode
    .SelectNodes("//code")
    .GroupBy(n => new { 
        Parent = n.ParentNode, 
        Index = n.NextSiblingIsCode() ? idx : idx++ 
    });

foreach (var group in nodes)
{
    var pre = HtmlNode.CreateNode("<pre class='brush: csharp'></pre>");
    pre.AppendChild(doc.CreateTextNode(
        string.Join(Environment.NewLine, group.Select(g => g.InnerText))
    ));
    group.Key.Parent.InsertBefore(pre, group.First());

    foreach (var code in group)
        code.Remove();
}
public static bool NextSiblingIsCode(this HtmlNode node)
{
    return (node.NextSibling != null && node.NextSibling.Name == "code") ||
        (node.NextSibling is HtmlTextNode && 
         node.NextSibling.NextSibling != null && 
         node.NextSibling.NextSibling.Name == "code");
}
var nodes = doc.DocumentNode.SelectNodes(
    "//code[name(preceding-sibling::*[1])!='code']"
);
foreach (var node in nodes)
{
    var pre = HtmlNode.CreateNode("<pre class='brush: csharp'></pre>");
    node.ParentNode.InsertBefore(pre, node);
    var content = string.Empty;
    var next = node;
    do
    {
        content += next.InnerText + Environment.NewLine;
        var previous = next;
        next = next.SelectSingleNode("following-sibling::*[1][name()='code']");
        previous.Remove();
    } while (next != null);
    pre.AppendChild(doc.CreateTextNode(
        content.TrimEnd(Environment.NewLine.ToCharArray())
    ));
}