如何清除重复的(父)节点?

时间:2018-11-18 04:01:51

标签: c# .net xml visual-studio-2017

我的输入有效载荷如下:

  <ns0:SourceFacilityCode FieldTypeToTranslate="Store">
    <ns0:SourceFacilityCode>CRA</ns0:SourceFacilityCode>
  </ns0:SourceFacilityCode>
  <ns0:Alex FieldTypeToTranslate="Facility">
    <ns0:Alex>CRA</ns0:Alex>
  </ns0:Alex>
  <ns0:Shoes>Red</Shoes>

如您所见,SourceFacilityCodeAlex都是不必要的。为了将其反序列化为具体的C#对象,我们需要将输入转换为以下形式:

    <ns0:SourceFacilityCode>CRA</ns0:SourceFacilityCode>
    <ns0:Alex>CRA</ns0:Alex>
    <ns0:Shoes>Red</nso0:Shoes>

如何将这种有效载荷转换成这样?

我尝试过的事情:

1. simple `string.Replace(a,b)`- but this is too messy and ungeneric
2. trying to load this into an Xml concrete object, but this was too difficult to do with the nested nodes having the same name
3. attempting to transform to json and then to concrete object

1 个答案:

答案 0 :(得分:1)

这是使用LINQ to XML的解决方案:

首先,将示例XML封装到Root元素中,使其成为可以由XDocument.Parse解析的有效XML:

var xml = @"<Root xmlns:ns0=""http://example.org/ns0"">
<ns0:SourceFacilityCode FieldTypeToTranslate=""Store"">
    <ns0:SourceFacilityCode>CRA</ns0:SourceFacilityCode>
  </ns0:SourceFacilityCode>
  <ns0:Alex FieldTypeToTranslate=""Facility"">
    <ns0:Alex>CRA</ns0:Alex>
  </ns0:Alex>
  <ns0:Shoes>Red</ns0:Shoes>
</Root>";

var doc = XDocument.Parse(xml);

然后,我们确定所有具有单个子元素的元素,这些子元素与该元素具有相同的名称,并且没有任何子元素:

var elementsWithSingleChildHavingSameName = doc.Root.Descendants()
    .Where(e => e.Elements().Count() == 1 
        && e.Elements().First().Name == e.Name 
        && !e.Elements().First().HasElements)
    .ToArray();

最后,遍历找到的元素,并在传输值时删除子元素:

foreach (var element in elementsWithSingleChildHavingSameName)
{
    var child = element.Elements().First();
    child.Remove();
    element.Value = child.Value;
}

要转换回字符串并删除Root包装器:

var cleanedUpXml = doc.ToString();
var output = Regex.Replace(cleanedUpXml, @"</?Root.*?>", "");