「自動XML合併」聽起來像一個相對簡單的要求,但是當您進入所有細節時,它會變得非常複雜。與c#或XSLT合併對於更具體的任務將更容易,如EF模型的answer。使用工具輔助手動合併也可以作爲選項(請參閱this SO question)。
對於參考(並提供有關複雜的想法),這裏是從Java世界的開源例如:XML merging made easy
回到原來的問題。在任務規範中有幾個大的灰色區域:當考慮2個元素時等效(具有相同的名稱,匹配所選屬性或所有屬性,或者在父元素中也具有相同的位置);如何處理的情況時,原始的或合併的XML有多個相當於元素等
下面的代碼是假設
- 我們只是在一瞬間關心的元素
- 元素相當於如果元素名稱,屬性名稱和屬性值匹配
- 一個元素不具有多個同名的屬性
- 全部等效來自合併文檔的元素將與源XML文檔中的第一個等效元素結合使用。
。
// determine which elements we consider the same
//
private static bool AreEquivalent(XElement a, XElement b)
{
if(a.Name != b.Name) return false;
if(!a.HasAttributes && !b.HasAttributes) return true;
if(!a.HasAttributes || !b.HasAttributes) return false;
if(a.Attributes().Count() != b.Attributes().Count()) return false;
return a.Attributes().All(attA => b.Attributes(attA.Name)
.Count(attB => attB.Value == attA.Value) != 0);
}
// Merge "merged" document B into "source" A
//
private static void MergeElements(XElement parentA, XElement parentB)
{
// merge per-element content from parentB into parentA
//
foreach (XElement childB in parentB.DescendantNodes())
{
// merge childB with first equivalent childA
// equivalent childB1, childB2,.. will be combined
//
bool isMatchFound = false;
foreach (XElement childA in parentA.Descendants())
{
if (AreEquivalent(childA, childB))
{
MergeElements(childA, childB);
isMatchFound = true;
break;
}
}
// if there is no equivalent childA, add childB into parentA
//
if (!isMatchFound) parentA.Add(childB);
}
}
它會產生期望的結果與原來的XML片斷,但如果輸入個XML比較複雜,有重複的元素,其結果將是更多...有趣:
public static void Test()
{
var a = XDocument.Parse(@"
<Root>
<LeafA>
<Item1 />
<Item2 />
<SubLeaf><X/></SubLeaf>
</LeafA>
<LeafB>
<Item1 />
<Item2 />
</LeafB>
</Root>");
var b = XDocument.Parse(@"
<Root>
<LeafB>
<Item5 />
<Item1 />
<Item6 />
</LeafB>
<LeafA Name=""X"">
<Item3 />
</LeafA>
<LeafA>
<Item3 />
</LeafA>
<LeafA>
<SubLeaf><Y/></SubLeaf>
</LeafA>
</Root>");
MergeElements(a.Root, b.Root);
Console.WriteLine("Merged document:\n{0}", a.Root);
}
這裏的合併文檔展示瞭如何從文檔B相當於元素合併起來:
<Root>
<LeafA>
<Item1 />
<Item2 />
<SubLeaf>
<X />
<Y />
</SubLeaf>
<Item3 />
</LeafA>
<LeafB>
<Item1 />
<Item2 />
<Item5 />
<Item6 />
</LeafB>
<LeafA Name="X">
<Item3 />
</LeafA>
</Root>
在文本編輯器中剪切並粘貼? – BoltClock 2011-05-18 12:56:32
@BoltClock我更喜歡一個腳本,因爲這些XML文件是自動生成的,並會頻繁更改。現在我的小單約2000行,包含多個需要合併的區域。 – Rachel 2011-05-18 12:58:08
什麼樣的腳本?如果有一種首選語言來編寫此腳本,您可能希望將其添加到標籤中。 – BoltClock 2011-05-18 12:58:29