【问题标题】:XML with sub nodes to csv format using linq使用 linq 将带有子节点的 XML 转换为 csv 格式
【发布时间】:2015-03-26 17:13:31
【问题描述】:

我需要一些帮助,将带有子节点的 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 中管理空值。

【问题讨论】:

  • @paqogomez - 如何在 linq 中为每个元素管理 null?服务节点丢失时如何处理?我是 linq 的新手。
  • @paqogomez - 您添加的重复参考帖子没有回答我的问题?您可以删除它以便其他人可以帮助我吗?
  • 除了你之外没有人看到,尽管其他人可以投票决定它是否真的重复。到目前为止,只有一个人同意我的观点。至于您的问题,在我看来,内联 if 语句可以解决您的问题。类似el.Element("Service").Element("PhoneNumber") == null ? "" : el.Element("Service").Element("PhoneNumber");
  • 我提供的重复链接很好地涵盖了该内联语句。

标签: c# xml linq export-to-csv


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    实际问题是custOrd它自己已经引用了&lt;Main&gt;,所以在custOrd上调用Element("Main")会返回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 转换为字符串是安全的,但如果有任何&lt;root&gt; 没有子元素&lt;service&gt;,您的代码将再次抛出空引用异常。

    【讨论】:

      猜你喜欢
      • 2020-01-25
      • 1970-01-01
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多