递归循环 xml 到 csv 与 xmlstarlet



我想将复杂的xml转换为csv。

<tests>
<test>
<name>AAA</name> 
<language>BBB</language> 
<Project>
<name>XXX</name>
<id>123</id>
</Project>
<fac>
<name>XXX</name>
<idt>
<number>99</number>
<idt>
<pers>YYY</pers>
</fac>
<fac>
<name>BBB</name>
<idt>
<number>70</number>
<idt>
<pers>MMM</pers>
</fac>
<fac>
<name>XXX</name>
<idt>
<number>40</number>
<idt>
<pers>XXX</pers>
</fac>
<date>2018</date>
</test>
<test>
<name>BBB</name> 
<language>CCC</language> 
<Project>
<name>AAA</name>
<id>12</id>
</Project>
<fac>
<name>YXX</name>
<idt>
<number>10</number>
<idt>
<pers>LLL</pers>
</fac>
<fac>
<name>BB</name>
<idt>
<number>7</number>
<idt>
<pers>MM</pers>
</fac>
<fac>
<name>XX</name>
<idt>
<number>40</number>
<idt>
<pers>XXX</pers>
</fac>
<date>2018</date>
</test>
<tests> 

到目前为止我做了什么:

xmlstarlet 
sel -T -t -m /tests/test 
-v "concat(name,';'
,language,';'
,Project/name,';'
,Project/id,';'
,fac/name,';'
,fac/idt/number,';'
,fac/pers,';'
,date)"
-n test.xml > test.csv

一切正常,但我只能获取第一个节点中包含的数据。我想要这样的东西:

对于第一个

name;language;name;id;data contained in the first node"fac";date 
name(same as first line);language(same as first line); etc..; data contained in the second "fac" node;date (same as first line)
etc... as much as there are face nodes

然后是第二个节点。

我不知道这是否可以使用 xmlstarlet 完成?

提前感谢您的帮助 射频低

如果你想为每个fac都有一个条目,这就是你应该匹配的。然后,您可以转到祖先test以获取所需的其他数据。

例。。。

xmlstarlet sel -T -t -m "//fac" -v "concat(ancestor::test/name,';',ancestor::test/language,';',ancestor::test/Project/name,';',ancestor::test/Project/id,';',name,';',idt/number,';',pers,';',ancestor::test/date)" -n test.xml

输出。。。

AAA;BBB;XXX;123;XXX;99;YYY;2018
AAA;BBB;XXX;123;BBB;70;MMM;2018
AAA;BBB;XXX;123;XXX;40;XXX;2018
BBB;CCC;AAA;12;YXX;10;LLL;2018
BBB;CCC;AAA;12;BB;7;MM;2018
BBB;CCC;AAA;12;XX;40;XXX;2018

以下是为可读性而细分的concat()...

concat(
ancestor::test/name,';',
ancestor::test/language,';',
ancestor::test/Project/name,';',
ancestor::test/Project/id,';',
name,';',
idt/number,';',
pers,';',
ancestor::test/date
)

尝试以下 xml linq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string XML_FILENAME = @"c:temptest.xml";
const string CSV_FILENAME = @"c:temptest.csv";
static void Main(string[] args)
{
string[] headers = {
"test name",
"language", 
"project name",
"project id",
"fac name",
"idt number",
"pers"
};
StreamWriter writer = new StreamWriter(CSV_FILENAME);
writer.WriteLine(string.Join(",", headers));
XDocument doc = XDocument.Load(XML_FILENAME);
foreach (XElement test in doc.Descendants("test"))
{
string testName = (string)test.Element("name");
string language = (string)test.Element("language");
XElement project = test.Element("Project");
string projectName = (string)project.Element("name");
string projectId = (string)project.Element("id");
foreach(XElement fac in test.Elements("fac"))
{
string facName = (string)fac.Element("name");
string number = (string)fac.Descendants("number").FirstOrDefault();
string pers = (string)fac.Element("pers");
string csvLine = string.Join(",", new string[] {
testName,
language,
projectName,
projectId,
facName,
number,
pers
});
writer.WriteLine(csvLine);
}
}

writer.Flush();
writer.Close();
}
}
}

最新更新