如何合并XML文件? [英] How can I merge XML files?

查看:78
本文介绍了如何合并XML文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two xml files that both have the same schema and I would like to merge into a single xml file. Is there an easy way to do this?

例如

<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合并"听起来像是一个相对简单的要求,但是当您进入所有细节时,它变得非常复杂.对于更具体的任务,例如在 answer 用于EF模型.也可以选择使用工具来进行手动合并(请参见这个问题).

"Automatic XML merge" sounds like a relatively simple requirement, but when you go into all the details, it gets complex pretty fast. Merge with c# or XSLT will be much easier for more specific task, like in the answer for EF model. Using tools to assist with a manual merge can also be an option (see this SO question).

作为参考(并让您对复杂性有所了解),这里有一个来自Java世界的开源示例:

For the reference (and to give an idea about complexity) here's an open-source example from Java world: XML merging made easy

回到原始问题.任务规范中的灰色区域很少:应将两个元素视为等效(具有相同的名称,匹配的选定属性或所有属性,或在父元素中具有相同的位置);当原始或合并的XML具有多个 equivalent 元素等时,如何处理情况.

Back to the original question. There are few big gray-ish areas in task specification: when 2 elements should be considered equivalent (have same name, matching selected or all attributes, or also have same position in the parent element); how to handle situation when original or merged XML have multiple equivalent elements etc.

下面的代码假设

  • 我们目前仅关注元素
  • 如果元素名称,属性名称和属性值匹配,则
  • 元素为等价
  • 一个元素没有多个具有相同名称的属性
  • 合并文档中的所有
  • 等效 元素将与源XML文档中的第一个等效元素组合.
  • we only care about elements at the moment
  • elements are equivalent if element names, attribute names, and attribute values match
  • an element doesn't have multiple attributes with the same name
  • all equivalent elements from merged document will be combined with the first equivalent element in the source XML document.

.

// 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更复杂并且具有重复的元素,则结果将更加...有趣:

It will produce desired result with the original XML snippets, but if input XMLs are more complex and have duplicate elements, the result will be more... interesting:

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中的等价元素是如何组合在一起的:

Here's merged document showing how equivalent elements from document B were combined together:

<Root>
  <LeafA>
    <Item1 />
    <Item2 />
    <SubLeaf>
      <X />
      <Y />
    </SubLeaf>
    <Item3 />
  </LeafA>
  <LeafB>
    <Item1 />
    <Item2 />
    <Item5 />
    <Item6 />
  </LeafB>
  <LeafA Name="X">
    <Item3 />
  </LeafA>
</Root>

这篇关于如何合并XML文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆