【问题标题】:How do I convert this special case XML into CSV?如何将此特殊情况的 XML 转换为 CSV?
【发布时间】:2014-02-03 13:05:36
【问题描述】:

我一直在尝试转换以下 XML

<root>
<data>
  <MEMBNO>11400116</MEMBNO> 
  <BASIC>15400.00</BASIC> 
  <BASIC>15000.00</BASIC> 
  <BASIC>14242.50</BASIC> 
</data>
<data>
   <MEMBNO>200</MEMBNO>
   <DOB>17/02/1975</DOB>
</data>
<data>
   <MEMBNO>16</MEMBNO>
   <BASIC>26354.00</BASIC>
</data>
</root>

像这样进入 CSV。

MEMBNO,BASIC,DOB,
11400116,"15400.00\v15000.00\v,14242.00",,
200,,17/12/1975,
16,26354.00,,

\v 是一个垂直制表符,它应该在 word 邮件合并发生时打印一个换行符。

你能帮我解决这个问题吗?

谢谢。

我没有任何进展。到目前为止,我没有任何代码。

【问题讨论】:

  • 我们之前只处理过 XML,我们使用了 dataset.ReadXML(),我们应该只获得一个数据表,但是使用这个 XML,我们得到了多个数据表,这会破坏邮件合并过程。所以我想到了转换为 CSV,真遗憾,我没有取得任何进展。对不起,我现在没有代码。
  • 我试图将多个数据表合并为一个,当 重复时我遇到了问题。我想把它改成 CSV,我在处理 XML 方面的经验很少,所以我需要提醒一下。

标签: c# xml csv


【解决方案1】:

假设一个&lt;DATA&gt;标签中只有&lt;BASIC&gt;标签可以多次出现,您可以尝试如下(详细情况请参见cmets,它使用XDocument和LINQ-to-XML):

var xml = @"<root>
<data>
  <MEMBNO>11400116</MEMBNO> 
  <BASIC>15400.00</BASIC> 
  <BASIC>15000.00</BASIC> 
  <BASIC>14242.50</BASIC> 
</data>
<data>
   <MEMBNO>200</MEMBNO>
   <DOB>17/02/1975</DOB>
</data>
<data>
   <MEMBNO>16</MEMBNO>
   <BASIC>26354.00</BASIC>
</data>
</root>";
var doc = XDocument.Parse(xml);
var output = "";
//loop through each <data>
foreach(var data in doc.Descendants("data"))
{
    //get <MEMBNO> under current <data>
    var membno = (string)data.Element("MEMBNO");
    //get all <BASIC> under current <data>
    var basic = string.Join("\v", data.Elements("BASIC").Select(o => (string)o).ToArray());
    if (!string.IsNullOrEmpty(basic)) basic = "\"" + basic + "\"";
    //get <DOB> under current <data>
    var dob = (string)data.Element("DOB");
    //construct line with format MEMBNO,BASIC,DOB,
    var line = string.Format("{0},{1},{2},", membno, basic, dob);

    output += line + Environment.NewLine;
}
Console.WriteLine(output);

可以调整上面的代码以适应每个&lt;data&gt; 下的未知元素数量和未知元素名称。检查下面的更新代码,这将产生与 .csv 样本相同的输出,而无需硬编码元素名称(假设 doc 变量与上述代码块中的相同):

//get distinct list of element name under <data>
var columns = doc.Root.Elements("data").Elements().Select(o => o.Name.LocalName).Distinct().ToList();
var output = "";
//add header to 'output' : MEMBNO,BASIC,DOB,
columns.ForEach(o => output += o + ",");
foreach (var data in doc.Descendants("data"))
{
    var line = Environment.NewLine;
    foreach (var column in columns)
    {
        var cellValue = string.Join("\v", data.Elements(column).Select(o => (string)o).ToArray());
        if (!string.IsNullOrEmpty(cellValue)) cellValue = "\"" + cellValue + "\"";
        line += cellValue + ",";
    }
    output += line;
}
Console.WriteLine(output);

【讨论】:

  • 谢谢@har07,对不起,我没有提到我们不知道 XML 文件中会有哪些元素。我提到的 XML 是一个示例,元素可以是任何东西,所以我可以硬编码标签名称。
  • 从上面的示例 xml 中,我怎么知道顺序应该是 MEMBNO、BASIC、DOB,而不是 MEMBNO、DOB、BASIC,或者顺序无关紧要?
  • 我的意思是处理xml后输出的csv文件中的列顺序,是不是特别的顺序?
  • 否 不必如此,邮件合并将按名称映射到特定列。感谢您的帮助。
  • 检查我的更新,如果需求与当前演示的略有不同,您将能够进一步调整代码。我假设&lt;data&gt; 下的每个元素都可以出现多次,并且应该以与您的示例中的&lt;BASIC&gt; 元素相同的方式处理。
猜你喜欢
  • 2013-06-14
  • 2020-04-13
  • 2020-05-11
  • 2011-03-20
  • 2021-07-31
  • 2014-04-23
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多