使用C#从Xml中删除重复节点

时间:2017-06-23 15:55:13

标签: c# xml

我有像

这样的xml
<xml>
 <Test>
  <TestData>
   <TestData>
    <Name>Alex</Name>
   </TestData>
  </TestData>
 </Test>
 <Name>
 <NameData>
   <NameData>
    <Name>Chris</Name>
   </NameData>
  </NameData>
 </Name>
</xml>

我想从xml中删除TestData和NameData的重复节点,以便xml看起来像这样

 <xml>
     <Test>
      <TestData>
        <Name>Alex</Name>
      </TestData>
     </Test>
     <Name>
     <NameData>
        <Name>Chris</Name>
      </NameData>
     </Name>
    </xml>

我试过寻找一些线索,但我遇到的每个建议都指定了节点名称。我有大量的xmls。我可以使用任何c#类/方法删除副本。

1 个答案:

答案 0 :(得分:2)

如果符合某些假设,那么LINQ to XML会使这个变得相当简单:

  • 没有带有&#34;三重复制的元素&#34;例如<TestData><TestData><TestData>。我确信解决这个问题是可行的,但这很棘手。
  • 我们不需要担心非元素儿童(例如,TestData有文本内容以及嵌套TestData元素)
  • 我们不需要担心属性

在这种情况下,只需检查是否有一个子元素,并且它与父元素具有相同的名称......然后替换它。

这里有一些代码可以做到这一点:

using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main(string[] args)
    {
        var doc = XDocument.Load("test.xml");
        var replacements = doc.Descendants()
            .Select(GetReplacementForParent)
            .Where(r => r != null)
            .ToList();
        foreach (var replacement in replacements)
        {
            replacement.Parent.ReplaceWith(replacement);
        }
        Console.WriteLine(doc);
    }

    static XElement GetReplacementForParent(XElement element)
    {
        var child = element.Elements(element.Name).FirstOrDefault();
        // TODO: Use a more efficient approach for counting children, maybe.
        // TODO: Check for non-element content? Check for attributes?
        return child != null && element.Elements().Count() == 1
            ? child : null;
    }
}