c# - 如何使用 C# 代码 LINQ 将多级 XML 扁平化为单级 XML

标签 c# xml linq

我浏览了一些关于扁平化 XML 结构的文章,以便每个元素及其值都转换为根元素上的属性。但是,我的要求是按照下面的示例展平输入 XML,但我找不到任何帮助。

我有一个如下所示的 XML 结构,

<RATES ID="1" RatesEffectivateDate="27/02/2014">
  <Type Name="Type1" Code="A">
    <Del ID="D1">
      <Field1>10</Field1>
      <Field2>20</Field2>
      <Field3>30</Field3>
      <Field4>40</Field4>
    </Del>
    <Del ID="D2">
      <Field1>50</Field1>
      <Field2>60</Field2>
      <Field3>70</Field3>
      <Field4>80</Field4>
    </Del>
  </Type>
  <Type Name="Type2" Code="B">
    <Del ID="D1">
      <Field1>110</Field1>
      <Field2>120</Field2>
      <Field3>130</Field3>
      <Field4>140</Field4>
    </Del>
    <Del ID="D3">
      <Field1>150</Field1>
      <Field2>160</Field2>
      <Field3>170</Field3>
      <Field4>180</Field4>
    </Del>
  </Type>
</RATES>

这需要标准化为以下格式,

<RATES>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D1</DelID>
    <Field1>10</Field1>
  </RATE>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D1</DelID>
    <Field2>20</Field2>
  </RATE>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D1</DelID>
    <Field3>30</Field3>
  </RATE>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D1</DelID>
    <Field4>40</Field4>
  </RATE>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D2</DelID>
    <Field1>50</Field1>
  </RATE>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D2</DelID>
    <Field2>60</Field2>
  </RATE>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D2</DelID>
    <Field3>70</Field3>
  </RATE>
  <RATE>
    <ID>Type1</ID>
    <Code>A</Code>
    <DelID>D2</DelID>
    <Field4>80</Field4>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D1</DelID>
    <Field1>110</Field1>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D1</DelID>
    <Field2>120</Field2>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D1</DelID>
    <Field3>130</Field3>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D1</DelID>
    <Field4>140</Field4>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D3</DelID>
    <Field1>50</Field1>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D3</DelID>
    <Field2>160</Field2>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D3</DelID>
    <Field3>170</Field3>
  </RATE>
  <RATE>
    <ID>Type2</ID>
    <Code>B</Code>
    <DelID>D3</DelID>
    <Field4>180</Field4>
  </RATE>
</RATES>

请对此提出建议,因为我是 LINQ 新手。谢谢!

最佳答案

我不知道是否有任何内置函数可以扁平化 XML,但我非常担心它们能否满足您的需求,因为根据您的示例,某些属性必须被忽略。

您最好使用 LINQ to XML,它可以非常轻松地转换此类文档,并且不需要大量代码。查看我的解决方案:

string origXml = "<RATES ID=\"1\" RatesEffectivateDate=\"27/02/2014\">\n  <Type Name=\"Type1\" Code=\"A\">\n    <Del ID=\"D1\">\n      <Field1>10</Field1>\n      <Field2>20</Field2>\n      <Field3>30</Field3>\n      <Field4>40</Field4>\n    </Del>\n    <Del ID=\"D2\">\n      <Field1>50</Field1>\n      <Field2>60</Field2>\n      <Field3>70</Field3>\n      <Field4>80</Field4>\n    </Del>\n  </Type>\n  <Type Name=\"Type2\" Code=\"B\">\n    <Del ID=\"D1\">\n      <Field1>110</Field1>\n      <Field2>120</Field2>\n      <Field3>130</Field3>\n      <Field4>140</Field4>\n    </Del>\n    <Del ID=\"D3\">\n      <Field1>150</Field1>\n      <Field2>160</Field2>\n      <Field3>170</Field3>\n      <Field4>180</Field4>\n    </Del>\n  </Type>\n</RATES>";
var xDoc = XDocument.Parse(origXml);

var resDoc = new XDocument(
    new XElement("RATES",
                    xDoc.Element("RATES")
                        .Elements("Type")
                        .SelectMany(typeEl =>
                                    typeEl.Elements("Del")
                                        .SelectMany(delEl =>
                                                    delEl.Elements()
                                                        .Select(fieldEl =>
                                                                new XElement("RATE",
                                                                                new XElement("ID", typeEl.Attribute("Name").Value),
                                                                                new XElement("Code", typeEl.Attribute("Code").Value),
                                                                                new XElement("DelID", delEl.Attribute("ID").Value),
                                                                                new XElement(fieldEl.Name, fieldEl.Value)))))
        ));

resDoc.Save("transformedDoc.xml", SaveOptions.None);

输出正是您为示例提供的内容。

关于c# - 如何使用 C# 代码 LINQ 将多级 XML 扁平化为单级 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23152638/

相关文章:

c# - 对于动态加载的 Razor 类库,ASP.NET Core 运行时编译失败并显示 "Cannot find compilation library location for package"

c# - 如何在 asp.net gridview 中获取 Item 值

c# - Entity Framework Core - 防止唯一索引上出现多个空值

c# - 加入两个单独的 linq 查询

c# - LINQ 查询跳过调试不执行下一行

用于扩展另一个产品的 C# 命名空间

java - 无法使用 JAXB 解析 XML 响应 - IndexOutOfBoundsException

java - 如何删除工具栏底部边距?

c# - 读取 XSD 为 "anyType"且属性 xsi 为 :type ="string" 的 XML 元素

c# - 如何使用 LINQ to XML 检索嵌套数组?