加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何合并XML文件?

发布时间:2020-12-15 03:53:32 所属栏目:百科 来源:网络整理
导读:我有两个xml文件,它们都具有相同的模式,我想合并到一个xml文件中.是否有捷径可寻? 例如, Root LeafA Item1 / Item2 / /LeafA LeafB Item1 / Item2 / /LeafB/Root Root LeafA Item3 / Item4 / /LeafA LeafB Item3 / Item4 / /LeafB/Root =包含新文件 Root Le
我有两个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>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读