-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMergeHtmlNode.linq
More file actions
94 lines (77 loc) · 2.92 KB
/
MergeHtmlNode.linq
File metadata and controls
94 lines (77 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<Query Kind="Statements">
<NuGetReference>HtmlAgilityPack</NuGetReference>
<Namespace>HtmlAgilityPack</Namespace>
</Query>
using System.Collections.Generic;
using System.Linq;
using HtmlAgilityPack;
//not complete
string h1 = @"<ul>
<li id='a'>apple</li>
<li id='b'>banana</li>
</ul>";
string h2 = @"<ul>
<li id='b'>BANANA</li>
<li id='c'>cherry</li>
</ul>";
var doc1 = new HtmlDocument(); doc1.LoadHtml(h1);
var doc2 = new HtmlDocument(); doc2.LoadHtml(h2);
// 只合併第一層 <ul>
var mergedUl = HtmlMerge
.MergeNodes(doc1.DocumentNode.SelectSingleNode("//ul"),
doc2.DocumentNode.SelectSingleNode("//ul"))
.First(); // 只取第一個 yield 結果
Console.WriteLine(mergedUl.OuterHtml);
public static class HtmlMerge
{
/// <summary>
/// 兩節點 lazy-merge:相同標籤才往下比對,差異節點直接 yield。
/// </summary>
public static IEnumerable<HtmlNode> MergeNodes(HtmlNode left, HtmlNode right)
{
if (left == null && right == null) yield break;
if (left == null) { yield return right; yield break; }
if (right == null) { yield return left; yield break; }
// 標籤不同 → 視為差異,各自輸出
if (!left.Name.Equals(right.Name))
{
yield return left;
yield return right;
yield break;
}
//--------------------------------------------------
// 1) 建立空殼 <tag></tag>
//--------------------------------------------------
var merged = HtmlNode.CreateNode($"<{left.Name}></{left.Name}>");
//--------------------------------------------------
// 2) 合併屬性(右邊覆蓋左邊)
//--------------------------------------------------
// 2) 合併屬性:右邊覆蓋左邊
foreach (var attr in left.Attributes)
merged.SetAttributeValue(attr.Name, attr.Value); // 先貼左邊
foreach (var attr in right.Attributes)
merged.SetAttributeValue(attr.Name, attr.Value); // 再貼右邊,會自動覆蓋
//--------------------------------------------------
// 3) 合併文字(可自行改為 diff 或標記)
//--------------------------------------------------
merged.InnerHtml = (left.InnerText ?? string.Empty) +
(right.InnerText ?? string.Empty);
//--------------------------------------------------
// 4) 遞迴子節點
//--------------------------------------------------
var lKids = left.ChildNodes.ToList();
var rKids = right.ChildNodes.ToList();
int max = System.Math.Max(lKids.Count, rKids.Count);
for (int i = 0; i < max; i++)
{
var l = i < lKids.Count ? lKids[i] : null;
var r = i < rKids.Count ? rKids[i] : null;
foreach (var sub in MergeNodes(l, r))
merged.AppendChild(sub);
}
//--------------------------------------------------
// 5) 把結果丟回上一層
//--------------------------------------------------
yield return merged;
}
}