如何使用不同的 headers 将 csv 转换为 xml
how to convert csv to xml with different headers
我有一个包含不同列 headers 的 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 包含不同的列 headers。
我期望的输出是;
<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)))));
使用TextFieldParser
读取csv文件并解析成类。
然后使用XDocument
在内存中建立一个xml文档,完成后写入文件
扩展链接示例,你可以这样做
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);
只需重命名相关元素并以正确的顺序包含它们即可。
// 已编辑
查看评论后,您似乎在数据中重复 header,以便将其用作元素名称。如果您可以控制 csv 生成,请删除此重复行,并将测试值简单地输出为 csv 中的第一个元素。
如果您无法控制 csv,您可以更改文本以便对其进行设置。这就是编辑后的示例所做的。
我有一个包含不同列 headers 的 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 包含不同的列 headers。
我期望的输出是;
<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)))));
使用TextFieldParser
读取csv文件并解析成类。
然后使用XDocument
在内存中建立一个xml文档,完成后写入文件
扩展链接示例,你可以这样做
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);
只需重命名相关元素并以正确的顺序包含它们即可。
// 已编辑
查看评论后,您似乎在数据中重复 header,以便将其用作元素名称。如果您可以控制 csv 生成,请删除此重复行,并将测试值简单地输出为 csv 中的第一个元素。
如果您无法控制 csv,您可以更改文本以便对其进行设置。这就是编辑后的示例所做的。