如何将csv转换为具有不同标头的xml

时间:2015-02-03 16:32:03

标签: c# xml linq csv

我有一个带有不同列标题的csv,我想将其转换为XML有效负载。

csv如下所示。

TEST1,APPLICATION_NAME,START_TIME,STOP_TIME,SERVICE_DESCRIPTION,FILING_STATUS,TIME_OF_LAST_UPDATE,RECORD_STATUS,ERROR_MESSAGE
,,20120101000000ES,20140131000000ES,New FGH Application,,,
,,20140304000000ES,20161231000000ES,New FGH Application,,,
,,20150109000000ES,20201231000000ES,New FGH Application,,,
TEST2,app,TOL,QUEUED
,nits,20120101000000ES,20201231000000ES

我试图用Linq做到这一点,但无法找到方法。另外,我真的不想像下面的例子那样指定列。

https://msdn.microsoft.com/en-us/library/bb387090

请注意,此csv具有不同的列标题。

我期待的输出是;

<Root>
  <TEST1>
    <APPLICATION_NAME></APPLICATION_NAME>
    <START_TIME>20120101000000ES</START_TIME>
    <STOP_TIME>20140131000000ES</STOP_TIME>
    <SERVICE_DESCRIPTION>New NITS Application</SERVICE_DESCRIPTION>
    <FILING_STATUS></FILING_STATUS>
    <TIME_OF_LAST_UPDATE></TIME_OF_LAST_UPDATE>
    <RECORD_STATUS></RECORD_STATUS>
  </TEST1>
  <TEST1>    
    <APPLICATION_NAME></APPLICATION_NAME>
    <START_TIME>20140304000000ES</START_TIME>
    <STOP_TIME>20161231000000ES</STOP_TIME>
    <SERVICE_DESCRIPTION>New NITS Application</SERVICE_DESCRIPTION>
    <FILING_STATUS></FILING_STATUS>
    <TIME_OF_LAST_UPDATE></TIME_OF_LAST_UPDATE>
    <RECORD_STATUS></RECORD_STATUS>
  </TEST1>
  <TEST1>
    <APPLICATION_NAME></APPLICATION_NAME>
    <START_TIME>20150109000000ES</START_TIME>
    <STOP_TIME>20201231000000ES</STOP_TIME>
    <SERVICE_DESCRIPTION>New NITS Application</SERVICE_DESCRIPTION>
    <FILING_STATUS></FILING_STATUS>
    <TIME_OF_LAST_UPDATE></TIME_OF_LAST_UPDATE>
    <RECORD_STATUS></RECORD_STATUS>
  </TEST1>
  <TEST2>
    <app>nits</app>
    <TOL>20120101000000ES</TOL>
    <QUEUED>20201231000000ES</QUEUED>
 </TEST2>
</root>

感谢您的帮助。

更新:这是我开始使用的。

string[] headers = lines[0].Split(',').Select(x => x.Trim('\"')).ToArray();
var xml = new XElement("root",
    lines.Where((line, index) => index > 0).Select(line => new XElement("TEST",
        line.Split(',').Select((column, index) => new XElement(headers[index], column)))));

2 个答案:

答案 0 :(得分:2)

扩展链接的示例,您可以执行此操作

string[] source = File.ReadAllLines("text.csv");
string IGNORE_ROW = "XXXXX";
List<string> data = new List<string>();
string test = "";
for (int i = 0; i < source.Length; i++)
{
    string[] _str = source[i].Split(',');
    if (String.IsNullOrWhiteSpace(_str[0])) _str[0] = test;
    else
    {
        test = _str[0];
        _str[0] = IGNORE_ROW;
    }

    source[i] = String.Join(",", _str);
}

XElement data = new XElement("Root",
    from str in source
    where str.StartsWith(IGNORE_ROW) == false
    let fields = str.Split(',')
    select new XElement(fields[0],
        new XElement("APPLICATION_NAME", fields[1]),
        new XElement("START_TIME", fields[2]),
        new XElement("STOP_TIME", fields[3]),
        new XElement("SERVICE_DESCRIPTION", fields[4]),
        new XElement("FILING_STATUS", fields[5]),
        new XElement("TIME_OF_LAST_UPDATE", fields[6]),
        new XElement("RECORD_STATUS", fields[7])
    )
);
Console.WriteLine(data);

只需重命名相关元素并按正确顺序包含它们即可。

//已编辑

在查看评论后,您似乎在重复数据中的标题,以便它可以用作元素名称。如果你可以控制csv生成,删除这个重复的行,只需输出测试值作为csv中的第一个元素。

如果您无法控制csv,则可以更改文本以便设置。这就是编辑过的例子。

答案 1 :(得分:0)

使用TextFieldParser读取csv文件并将其解析为类。 然后使用XDocument在内存中构建一个xml文档,并在文件完成后将其写入文件。