Первый подход: выбрать все узлы <code>
, сгруппировать их и создать узел <pre>
для каждой группы:
<code>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.AppendChild (doc.CreateTextNode (string.Join (Environment).NewLine, group.Select (g => g.InnerText)))); group.Key.Parent.InsertBefore (pre, group.First ()); foreach (код var в группе) code.Remove ();}
Поле группировки здесь представляет собой комбинированное поле родительского узла и индекса группы, которое увеличивается при обнаружении новой группы. Также я использовал NextSiblingIsCode
метод расширения здесь:
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");
}
Используется для определения, является ли следующий брат или сестра <code>
узлом.Второй подход: выберите только верхний <code>
узел каждой группы, затем выполните итерацию по каждому из этих узлов, чтобы найти следующий <code>
узел до первого не <code>
узла.Я использовал xpath
здесь:
<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'>
"); node.ParentNode.InsertBefore (pre, node); var content = string.Empty; var next = node; do {content + = next.InnerText + Environment.NewLine; var previous = next; next = next.SelectSingleNode ("follow-sibling :: * [1] [name () = 'code']"); previous.Remove ();} while (next! = Null);pre.AppendChild (doc.CreateTextNode (content.TrimEnd (Environment.NewLine.ToCharArray ())));}