我经历了关于展平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的新手。谢谢!
答案 0 :(得分:2)
我不知道是否有任何内置函数可以扩展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);
输出正是您为示例提供的。
答案 1 :(得分:2)
你可以这样做:
var xmlDocument = XDocument.Load("path");
var rates = new List<XElement>();
foreach (var type in xmlDocument.Descendants("Type"))
{
foreach (var del in type.Elements("Del"))
{
foreach (var field in del.Elements())
{
XElement rate = new XElement("RATE",
new XElement("ID", (string) type.Attribute("Name")),
new XElement("Code", (string) type.Attribute("Code")),
new XElement("DelID", (string) del.Attribute("ID")),
new XElement(field.Name, (string) field));
rates.Add(rate);
}
}
}
XElement root = new XElement("RATES");
root.Add(rates);
root.Save("newFile.xml");
使用LINQ
代替循环的另一种方法,但我认为这不太可读
var xmlDocument = XDocument.Load("path");
var newXML = new XElement("RATES",
xmlDocument.Descendants()
.Where(x => x.Name.ToString().StartsWith("Field"))
.Select(
x =>
new XElement("RATE",
new XElement("ID", (string) x.Parent.Parent.Attribute("Name")),
new XElement("Code", (string) x.Parent.Parent.Attribute("Code")),
new XElement("DelID", (string) x.Parent.Attribute("ID")),
new XElement(x.Name, (string) x))));
newXML.Save("newFile.xml");