“自动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