使用C#将XML转换为CSV

问题描述 投票:-1回答:3

如何在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>

我应该在CSV文件中得到这样的内容:

891258;450;39;229

891258;432;44;34

C#代码:

我面对这个代码的问题是我无法检索TAG <impot>的descandent

   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
3个回答
0
投票

您的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);
    }
}

0
投票

好吧,首先我尝试重新格式化你的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

通过内存 - 希望这是检索属性的正确方法。


0
投票

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

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);
}

另请注意用于属性的语法。

© www.soinside.com 2019 - 2024. All rights reserved.