C# 使用linq将带有子节点的XML转换为csv格式

C# 使用linq将带有子节点的XML转换为csv格式,c#,xml,linq,export-to-csv,C#,Xml,Linq,Export To Csv,我需要一些帮助,将带有子节点的XML转换为csv文件 以下是我的XML: <Main> <root> <Name>Sample name1</Name> <StreetAddress>Sample Address1</StreetAddress> <Service> <Type>Outlet</Type> <PhoneNumber&

我需要一些帮助,将带有子节点的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>
尝试了我从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
它本身已经引用了
,因此在
custOrd
上调用
元素(“Main”)
将返回
null
,并调用
元素(“root”)
null
上的
肯定会触发null引用异常

要解决该问题,您可以将
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
强制转换为字符串是安全的,但是如果有任何
没有子元素
您的代码将再次抛出null引用异常。

正如其他人在加载或解析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);

@paqogomez的可能重复-如何在linq中为每个元素管理null?当服务节点丢失时,如何处理?我是linq的新手。@paqogomez-你添加的重复参考帖子没有回答我的问题?你能把它移走让其他人帮我吗?除了你没人看到,尽管其他人可以投票决定它是否真的是重复的。到目前为止,只有一个人同意我的观点。至于你的问题,在我看来,内联if语句可以解决你的问题。类似于
el.Element(“服务”).Element(“电话号码”)==null?“”:el.Element(“服务”).Element(“电话号码”),我提供的重复链接中很好地介绍了内联语句。
        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);