【问题标题】:Convert a XML to CSV using C#使用 C# 将 XML 转换为 CSV
【发布时间】:2017-12-21 00:49:30
【问题描述】:

如何在 C# 中将 XML 文件转换为 CSV 文件,只显示这些标签:<original-impot-no>, <price>, <Small-price>, <Big-price>?

示例 XML 代码:表示多行中的一行,每行可能包含多个<product-lineitem>Tags

<?xml version="1.0" encoding="UTF-8"?>
<impots xmlns="http://www.google.com/xml/impot//20016-02-31">
  <impot impot-no="W0110891258">
    <impot-date>2017-12-10T22:33:35.000Z</impot-date>
    <prop-by>Yallo</prop-by>
    <original-impot-no>891258</original-impot-no>
    <currency>EUR</currency>
    <server-locale>Esp</server-locale>
    <lax>gross</lax>
    <current-impot-no>123358</current-impot-no>
    <product-lineitems>
       <product-lineitem>
            <price>450</price>
            <red>6.50</red>
            <Small-price>39</Small-price>
            <Big-price>3229</Big-price>
            <lineitem-text>Grand create</lineitem-text>
            <basis>234.00</basis>
        </product-lineitem>
    </product-lineitems>
       <product-lineitem>
            <price>432</price>
            <red>12</red>
            <Small-price>44</Small-price>
            <Big-price>34</Big-price>
            <lineitem-text>Small create</lineitem-text>
            <basis>44.00</basis>
       </product-lineitem>
    </product-lineitems>
  </impot>
</impots>

我应该在 y CSV 文件中得到这样的东西:

891258;450;39;229

891258;432;44;34

C# 代码:

我使用此代码面临的问题是我无法检索 TAG &lt;impot&gt; 的倒数

   XmlTextReader xtr = new XmlTextReader(@"C:\Temp_Convert\Impot.xml");
            StringBuilder dataToBeWritten = new StringBuilder();
            while (xtr.Read())
            {

                    if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "original-impot-no")
                    {
                        string s1 = xtr.ReadElementString();
                        dataToBeWritten.Append(s1);
                        dataToBeWritten.Append(";");
                    }
                    else if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "price")
                    {
                        string s2 = xtr.ReadElementString();
                        dataToBeWritten.Append(s2);
                        dataToBeWritten.Append(";");

                    }
                    else if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "Small-price")
                    {
                        string s2 = xtr.ReadElementString();
                        dataToBeWritten.Append(s2);
                        dataToBeWritten.Append(";");
                        dataToBeWritten.Append(0);
                        dataToBeWritten.Append(Environment.NewLine);
                    }
                        else if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "Big-price")
                    {
                        string s2 = xtr.ReadElementString();
                        dataToBeWritten.Append(s2);
                        dataToBeWritten.Append(";");
                        dataToBeWritten.Append(0);
                        dataToBeWritten.Append(Environment.NewLine);
                    }
                }

                File.WriteAllText(@"C:\Temp_Convert\Impot.csv", dataToBeWritten.ToString());

            }

有人可以提出解决方案吗,非常感谢您。

【问题讨论】:

    标签: c# .net linq-to-xml xmlreader


    【解决方案1】:

    您的 XML 无效。我想这是正确的格式。

    <?xml version="1.0" encoding="UTF-8"?>
    <impots xmlns="http://www.google.com/xml/impot//20016-02-31">
       <impot impot-no="W0110891258">
          <impot-date>2017-12-10T22:33:35.000Z</impot-date>
          <prop-by>Yallo</prop-by>
          <original-impot-no>891258</original-impot-no>
          <currency>EUR</currency>
          <server-locale>Esp</server-locale>
          <lax>gross</lax>
          <current-impot-no>123358</current-impot-no>
          <product-lineitems>
             <product-lineitem>
                <price>450</price>
                <red>6.50</red>
                <Small-price>39.00</Small-price>
                <Big-price>3229.00</Big-price>
                <lineitem-text>Grand create</lineitem-text>
                <basis>234.00</basis>
             </product-lineitem>
          </product-lineitems>
          <product-lineitems>
             <product-lineitem>
                <price>432</price>
                <red>12</red>
                <Small-price>44.00</Small-price>
                <Big-price>34.00</Big-price>
                <lineitem-text>Small create</lineitem-text>
                <basis>44.00</basis>
             </product-lineitem>
          </product-lineitems>
       </impot>
    </impots>
    

    您无法检索后代,因为您没有包含命名空间 http://www.google.com/xml/impot//20016-02-31

    代码应该是这样的。

    XNamespace ns = "http://www.google.com/xml/impot//20016-02-31";
    var results = xDocument.Descendants(ns + "impot");
    

    然后,您需要修改查询以检索您需要的元素。

    这里是示例。我假设product-lineitems 只有一个孩子product-lineitem

    var results = xDocument.Descendants(ns + "impot").Select(x => new {
        ImpotNo = x.Attribute("impot-no")?.Value,
        ProductLineItems = x.Descendants(ns + "product-lineitems").Select(y => new
        {
            Item = y.Descendants(ns + "product-lineitem").Select(z => new
            {
                Price = z.Element(ns + "price")?.Value,
                SmallPrice = z.Element(ns + "Small-price")?.Value,
                BigPrice = z.Element(ns + "Big-price")?.Value,
            }).FirstOrDefault()
        })
    });
    
    foreach (var result in results)
    {
        foreach (var productLine in result.ProductLineItems)
        {
            dataToBeWritten.Append(result.ImpotNo);
            dataToBeWritten.Append(";");
            dataToBeWritten.Append(productLine.Item.Price);
            dataToBeWritten.Append(";");
            dataToBeWritten.Append(productLine.Item.SmallPrice);
            dataToBeWritten.Append(";");
            dataToBeWritten.Append(productLine.Item.BigPrice);
            dataToBeWritten.Append(";");
            dataToBeWritten.Append(0);
            dataToBeWritten.Append(Environment.NewLine);
        }
    }
    

    【讨论】:

    • 我已经添加了你提到的命名空间,但是我得到了一个空白的 csv 文件
    • 您需要修改您的查询以满足您的需要。我已经编辑了我的帖子。
    • 谢谢!它有效,但我有几个孩子 product-lineitem 一个 impot-no ,每个 impot-no 都可以复制,这取决于 product-lineitem
    • 如果它解决了您在问题中的主要问题,请接受答案。如果product-lineitem 可以有多个,您可以删除FirstOrDefault()。然后,您需要在Items 上再循环一次来构造结果。而且你需要自己做重复检查。祝你好运。
    • 对不起,你能提供答案吗?
    【解决方案2】:

    嗯,首先我尝试重新格式化您的 XML 以使其更具可读性,但标签结构似乎仍然错误...

    <impots
        xmlns="http://www.google.com/xml/impot//20016-02-31">
        <impot impot-no="W0110891258">
            <impot-date>2017-12-10T22:33:35.000Z</impot-date>
            <prop-by>Yallo</prop-by>
            <original-impot-no>891258</original-impot-no>
            <currency>EUR</currency>
            <server-locale>Esp</server-locale>
            <lax>gross</lax>
            <current-impot-no>123358</current-impot-no>
            <product-lineitems>
                <product-lineitem>
                    <price>450</price>
                    <red>6.50</red>
                    <Small-price>39.00</Small-price>
                    <Big-price>3229.00</Big-price>
                    <lineitem-text>Grand create</lineitem-text>
                    <basis>234.00</basis>
    -
                </product-lineitems>
    -
            </product-lineitem>
            <product-lineitems>
                <product-lineitem>
                    <price>432</price>
                    <red>12</red>
                    <Small-price>44.00</Small-price>
                    <Big-price>34.00</Big-price>
                    <lineitem-text>Small create</lineitem-text>
                    <basis>44.00</basis>
                </product-lineitems>
            </product-lineitem>
    

    不过,我猜这行是不正确的,因为“impot-no”是一个属性...

    impot-no = (string)x.Element("impot impot-no")
    

    也许你的意思是那条线是……

    impot-no = (string)x.Attribute("impot-no").Value
    

    凭记忆进行——希望这是检索属性的正确方法。

    【讨论】:

      【解决方案3】:

      查看以下代码。请注意使用SelectMany 来获取导入项以构建所需的对象模型。

      XNamespace ns = "http://www.google.com/xml/impot//20016-02-31";
      var results = xDocument.Descendants(ns + "impot")
          .SelectMany(impot => impot.Descendants(impot.Name.Namespace + "product-lineitem")
              .Select(item => new {
                  ImpotNo = (string)impot.Element(impot.Name.Namespace + "original-impot-no"),
                  Price = (string)item.Element(item.Name.Namespace + "price"),
                  SmallPrice = (string)item.Element(item.Name.Namespace + "Small-price"),
                  BigPrice = (string)item.Element(item.Name.Namespace + "Big-price"),
              })
          ).ToList();
      
      
      for (int i = 0; i < results.Count; i++) {
          dataToBeWritten.Append(results[i].ImpotNo);
          dataToBeWritten.Append(";");
          dataToBeWritten.Append(results[i].Price);
          dataToBeWritten.Append(";");
          dataToBeWritten.Append(results[i].SmallPrice);
          dataToBeWritten.Append(";");
          dataToBeWritten.Append(results[i].BigPrice);
          dataToBeWritten.Append(";");
          dataToBeWritten.Append(0);
          dataToBeWritten.Append(Environment.NewLine);
      }
      

      还要注意用于属性的语法。

      【讨论】:

      • 谢谢你的回答,问题是我无法获取root impot
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-02
      • 2021-04-29
      • 2017-05-23
      • 2011-10-28
      相关资源
      最近更新 更多