c# – 如何合并XML文件?

我有两个xml文件,它们都具有相同的模式,我想合并到一个xml文件中.是否有捷径可寻?

例如,

<Root>
    <LeafA>
        <Item1 />
        <Item2 />
    </LeafA>
    <LeafB>
        <Item1 />
        <Item2 />
    </LeafB>
</Root>
<Root>
    <LeafA>
        <Item3 />
        <Item4 />
    </LeafA>
    <LeafB>
        <Item3 />
        <Item4 />
    </LeafB>
</Root>

=包含新文件

<Root>
    <LeafA>
        <Item1 />
        <Item2 />
        <Item3 />
        <Item4 />
    </LeafA>
    <LeafB>
        <Item1 />
        <Item2 />
        <Item3 />
        <Item4 />
    </LeafB>
</Root>

解决方法

自动XML合并”听起来像是一个相对简单的要求,但是当你深入研究所有细节时,它会变得非常复杂.与更具体的任务相比,使用c#或XSLT更容易,例如在 answer for EF模型中.使用工具来协助手动合并也是一种选择(见 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>

相关文章

在项目中使用SharpZipLib压缩文件夹的时候,遇到如果目录较深,则压缩包中的文件夹同样比较深的问题。比...
项目需要,几十万张照片需要计算出每个照片的特征值(调用C++编写的DLL)。 业务流程:选择照片...
var array = new byte[4]; var i = Encoding.UTF8.GetBytes(100.ToString(&quot;x2&quot;));//...
其实很简单,因为Combox的Item是一个K/V的object,那么就可以把它的items转换成IEnumerable&lt;Dic...
把.net4.6安装包打包进安装程序。 关键脚本如下: 头部引用字符串对比库 !include &quot;WordFunc....
项目需求(Winform)可以批量打印某个模板,经过百度和摸索,使用iTextSharp+ZXing.NetʿreeSp...