XML 使用 linq 将子节点转换为 csv 格式
XML with sub nodes to csv format using linq
我需要一些帮助将带有子节点的 XML 转换为 csv 文件。
这是我的 XML:
<Main>
<root>
<Name>Sample name1</Name>
<StreetAddress>Sample Address1</StreetAddress>
<Service>
<Type>Outlet</Type>
<PhoneNumber></PhoneNumber>
<Openweekday>Closed</Openweekday>
</Service>
<Service>
<Type>Mall</Type>
<PhoneNumber></PhoneNumber>
<Openweekday>Closed</Openweekday>
</Service>
</root>
<root>
<Name>Sample name2</Name>
<StreetAddress>Sample Address2</StreetAddress>
<Service>
<Type>Shop</Type>
<PhoneNumber></PhoneNumber>
<Openweekday>Closed</Openweekday>
</Service>
</Main>
预期 CSV 结果:
Name,StreetAddress,Type,PhoneNumber,OpenweekDay,Type,PhoneNumber,OpenweekDay
Sample name1,Sample Address1,Outlet,,Closed,Mall,,Closed
Sample name2,Sample Address2,Shop,,Closed
尝试了我从 MSDN 获得的这段代码。但它抛出一个空异常 -
XElement custOrd = XElement.Load("xxx.xml");
string csv =
(from el in custOrd.Element("Main").Elements("root")
select
String.Format("{0},{1},{2},{3},{4},{5},{6},{7}",
(string)el.Attribute("Name"),
(string)el.Element("StreetAddress"),
(string)el.Element("Service").Element("Type"),
(string)el.Element("Service").Element("PhoneNumber"),
(string)el.Element("Service").Element("Openweekday"),
(string)el.Element("Service").Element("Type"),
(string)el.Element("Service").Element("PhoneNumber"),
(string)el.Element("Service").Element("Openweekday"),
Environment.NewLine
)
)
.Aggregate(
new StringBuilder(),
(sb, s) => sb.Append(s),
sb => sb.ToString()
);
Console.WriteLine(csv);
告诉我如何在 linq 中管理空值。
实际问题是 custOrd
它自己已经引用了 <Main>
,所以在 custOrd
上调用 Element("Main")
将 return null
,并且在 null
上调用 Elements("root")
肯定会触发空引用异常。
要解决该问题,您可以将 custOrd
更改为 XDocument
类型:
XDocument custOrd = XDocument.Load("xxx.xml");
...或者简单地删除 .Element("Main")
调用:
XElement custOrd = XElement.Load("xxx.xml");
string csv =
(from el in custOrd.Elements("root")
......
......
将 null
转换为字符串是安全的,但是如果 <root>
没有子元素 <service>
,您的代码将再次抛出空引用异常。
正如其他人在加载或解析 xml 时提到的那样,已经引用了 main,因此您的起点应该是 root。
这将为您提供所需的结构。
XElement dataSet1Tree = XElement.Parse(xml);
var dataSet1List = dataSet1Tree.Elements().Select(
root => new
{
Name = (string)root.Element("Name"),
StreetAddress = (string)root.Element("StreetAddress"),
Service = root.Elements("Service")
.Select(service => new
{
Type = (string)service.Element("Type"),
PhoneNumber = (string)service.Element("PhoneNumber"),
OpenWeekDay = (string)service.Element("Openweekday")
})
}).SelectMany(root => root.Service, (root, service) => new
{
Name = root.Name,
StreetAddress = root.StreetAddress ,
Type = service.Type,
PhoneNumber = service.PhoneNumber,
OpenWeekDay = service.OpenWeekDay
}).Aggregate("",(sb,s)=> sb +=string.Format("{0},{1},{2},{3},{4}",
s.Name,
s.StreetAddress,
s.Type,
s.PhoneNumber,
s.OpenWeekDay)+"\r\n");
Console.WriteLine(dataSet1List);
我需要一些帮助将带有子节点的 XML 转换为 csv 文件。
这是我的 XML:
<Main>
<root>
<Name>Sample name1</Name>
<StreetAddress>Sample Address1</StreetAddress>
<Service>
<Type>Outlet</Type>
<PhoneNumber></PhoneNumber>
<Openweekday>Closed</Openweekday>
</Service>
<Service>
<Type>Mall</Type>
<PhoneNumber></PhoneNumber>
<Openweekday>Closed</Openweekday>
</Service>
</root>
<root>
<Name>Sample name2</Name>
<StreetAddress>Sample Address2</StreetAddress>
<Service>
<Type>Shop</Type>
<PhoneNumber></PhoneNumber>
<Openweekday>Closed</Openweekday>
</Service>
</Main>
预期 CSV 结果:
Name,StreetAddress,Type,PhoneNumber,OpenweekDay,Type,PhoneNumber,OpenweekDay
Sample name1,Sample Address1,Outlet,,Closed,Mall,,Closed
Sample name2,Sample Address2,Shop,,Closed
尝试了我从 MSDN 获得的这段代码。但它抛出一个空异常 -
XElement custOrd = XElement.Load("xxx.xml");
string csv =
(from el in custOrd.Element("Main").Elements("root")
select
String.Format("{0},{1},{2},{3},{4},{5},{6},{7}",
(string)el.Attribute("Name"),
(string)el.Element("StreetAddress"),
(string)el.Element("Service").Element("Type"),
(string)el.Element("Service").Element("PhoneNumber"),
(string)el.Element("Service").Element("Openweekday"),
(string)el.Element("Service").Element("Type"),
(string)el.Element("Service").Element("PhoneNumber"),
(string)el.Element("Service").Element("Openweekday"),
Environment.NewLine
)
)
.Aggregate(
new StringBuilder(),
(sb, s) => sb.Append(s),
sb => sb.ToString()
);
Console.WriteLine(csv);
告诉我如何在 linq 中管理空值。
实际问题是 custOrd
它自己已经引用了 <Main>
,所以在 custOrd
上调用 Element("Main")
将 return null
,并且在 null
上调用 Elements("root")
肯定会触发空引用异常。
要解决该问题,您可以将 custOrd
更改为 XDocument
类型:
XDocument custOrd = XDocument.Load("xxx.xml");
...或者简单地删除 .Element("Main")
调用:
XElement custOrd = XElement.Load("xxx.xml");
string csv =
(from el in custOrd.Elements("root")
......
......
将 null
转换为字符串是安全的,但是如果 <root>
没有子元素 <service>
,您的代码将再次抛出空引用异常。
正如其他人在加载或解析 xml 时提到的那样,已经引用了 main,因此您的起点应该是 root。 这将为您提供所需的结构。
XElement dataSet1Tree = XElement.Parse(xml);
var dataSet1List = dataSet1Tree.Elements().Select(
root => new
{
Name = (string)root.Element("Name"),
StreetAddress = (string)root.Element("StreetAddress"),
Service = root.Elements("Service")
.Select(service => new
{
Type = (string)service.Element("Type"),
PhoneNumber = (string)service.Element("PhoneNumber"),
OpenWeekDay = (string)service.Element("Openweekday")
})
}).SelectMany(root => root.Service, (root, service) => new
{
Name = root.Name,
StreetAddress = root.StreetAddress ,
Type = service.Type,
PhoneNumber = service.PhoneNumber,
OpenWeekDay = service.OpenWeekDay
}).Aggregate("",(sb,s)=> sb +=string.Format("{0},{1},{2},{3},{4}",
s.Name,
s.StreetAddress,
s.Type,
s.PhoneNumber,
s.OpenWeekDay)+"\r\n");
Console.WriteLine(dataSet1List);