将 CSV 文件转换为 XML

Posted

技术标签:

【中文标题】将 CSV 文件转换为 XML【英文标题】:Convert CSV file to XML 【发布时间】:2011-03-05 10:07:59 【问题描述】:

我需要将 CSV 转换为 XML 文档。到目前为止,我看到的示例都显示了如何在 CSV 中使用固定数量的列来执行此操作。

到目前为止,我使用 LINQ:

String[] File = File.ReadAllLines(@"C:\text.csv");

        String xml = "";

        XElement top = new XElement("TopElement",

        from items in File

        let fields = items.Split(';')

        select new XElement("Item",

        new XElement("Column1", fields[0]),

        new XElement("Column2", fields[1]),

        new XElement("Column3", fields[2]),

        new XElement("Column4", fields[3]),

        new XElement("Column5", fields[4])

        )

        );

        File.WriteAllText(@"C:\xmlout.xml", xml + top.ToString());

这是针对固定数量的列,但我的 .CSV 在每行有不同数量的列。

根据 .CSV 的每一行中有多少单词(列),您如何将某种循环放入其中?

谢谢

【问题讨论】:

【参考方案1】:
var lines = File.ReadAllLines(@"C:\text.csv");

var xml = new XElement("TopElement",
   lines.Select(line => new XElement("Item",
      line.Split(';')
          .Select((column, index) => new XElement("Column" + index, column)))));

xml.Save(@"C:\xmlout.xml");

输入:

A;B;C
D;E;F
G;H

输出:

<TopElement>
  <Item>
    <Column0>A</Column0>
    <Column1>B</Column1>
    <Column2>C</Column2>
  </Item>
  <Item>
    <Column0>D</Column0>
    <Column1>E</Column1>
    <Column2>F</Column2>
  </Item>
  <Item>
    <Column0>G</Column0>
    <Column1>H</Column1>
  </Item>
</TopElement>

【讨论】:

非常接近。但是我需要将每行上的每个单词都分开,用 ; 分隔。因此,输出 XML 将如下所示: wordwordwordwordwordwordword 我几乎和我发布的代码一样,但我只得到每行的第一个单词。所以我需要添加某种循环,为每行上的每个单词添加一个 Column 元素,由 ; @Soeren:我的解决方案不就是这样吗?我添加了一个示例以进行说明。 这很好用。 line.Split(';') 部分不在第一个示例中,我尝试自己添加它。我只是不知道如何添加它。我需要再研究一下这个 LINQ 的东西。感谢您的帮助。 很棒的帖子...我用了一些零碎的东西,它完美地工作 回复有点晚,但是如果您的列可以在带引号的列中包含分隔符,请注意 string .split() 不会注意带引号的字符串。示例: var x = "\"Quoted;string\""; var words = x.Split(';');词[0]; // "Quoted words[1]; // "string" 所以,如果你的分隔符是一个普通字符,你会有额外的数据列。【参考方案2】:

如果您想使用标题作为元素名称:

var lines = File.ReadAllLines(@"C:\text.csv");
string[] headers = lines[0].Split(',').Select(x => x.Trim('\"')).ToArray();

var xml = new XElement("TopElement",
   lines.Where((line, index) => index > 0).Select(line => new XElement("Item",
      line.Split(',').Select((column, index) => new XElement(headers[index], column)))));

xml.Save(@"C:\xmlout.xml");

【讨论】:

有没有办法将此示例转换为 JSON?【参考方案3】:

我编写了一个派生自 Vlax 的 sn-p 的类。 此外,我还提供了一个单元测试来记录工作流程。

单元测试:

[TestMethod]
public void convert_csv_to_xml()

    // Setup
    var csvPath = @"Testware\vendor.csv";
    var xmlPath = @"Testware\vendor.xml";

    // Test
    var success = DocumentConverter.Instance.CsvToXml(csvPath, xmlPath);

    // Verify
    var expected = File.Exists(xmlPath) && success;
    Assert.AreEqual(true, expected);

CSV 转 XML:

public class DocumentConverter

    #region Singleton
    static DocumentConverter _documentConverter = null;

    private DocumentConverter()  

    public static DocumentConverter Instance
    
        get
        
            if (_documentConverter == null)
            
                _documentConverter = new DocumentConverter();
            

            return _documentConverter;
        
    
    #endregion

    public bool CsvToXml(string sourcePath, string destinationPath)
    
        var success = false;

        var fileExists = File.Exists(sourcePath);

        if (!fileExists)
        
            return success;
        

        var formatedLines = LoadCsv(sourcePath);
        var headers = formatedLines[0].Split(',').Select(x => x.Trim('\"').Replace(" ", string.Empty)).ToArray();

        var xml = new XElement("VendorParts",
           formatedLines.Where((line, index) => index > 0).
               Select(line => new XElement("Part",
                  line.Split(',').Select((field, index) => new XElement(headers[index], field)))));

        try
        
            xml.Save(destinationPath);

            success = true;
        
        catch (Exception ex)
        
            success = false;

            var baseException = ex.GetBaseException();
            Debug.Write(baseException.Message);
        

        return success;
    

    private List<string> LoadCsv(string sourcePath)
    
        var lines = File.ReadAllLines(sourcePath).ToList();

        var formatedLines = new List<string>();

        foreach (var line in lines)
        
            var formatedLine = line.TrimEnd(',');
            formatedLines.Add(formatedLine);
        
        return formatedLines;
    

注意:

我扩展了 Vlax 的解决方案,删除了导致运行时异常的每个 CSV 行条目的尾随逗号,该异常基于与列标题相关的索引超出范围。

【讨论】:

伟大的实现! 代码工作正常,但如果我的 csv 中有逗号分隔值,它就无法工作。【参考方案4】:

Cinchoo ETL - 一个开源库,只需几行代码即可轻松将 CSV 转换为 Xml

对于示例 CSV:

string csv = @"Id, Name, City
1, Tom, NY
2, Mark, NJ
3, Lou, FL
4, Smith, PA
5, Raj, DC
";

StringBuilder sb = new StringBuilder();

using (var p = ChoCSVReader.LoadText(csv)
    .WithFirstLineHeader()
    )

    using (var w = new ChoXmlWriter(sb)
        .Configure(c => c.RootName = "Employees")
        .Configure(c => c.NodeName = "Employee")
        )
        w.Write(p);


Console.WriteLine(sb.ToString());

输出 Xml:

<Employees>
  <Employee>
    <Id>1</Id>
    <Name>Tom</Name>
    <City>NY</City>
  </Employee>
  <Employee>
    <Id>2</Id>
    <Name>Mark</Name>
    <City>NJ</City>
  </Employee>
  <Employee>
    <Id>3</Id>
    <Name>Lou</Name>
    <City>FL</City>
  </Employee>
  <Employee>
    <Id>4</Id>
    <Name>Smith</Name>
    <City>PA</City>
  </Employee>
  <Employee>
    <Id>5</Id>
    <Name>Raj</Name>
    <City>DC</City>
  </Employee>
</Employees>

查看 CodeProject 文章以获得更多帮助。

免责声明:我是这个库的作者。

【讨论】:

【参考方案5】:

这里提供了一个不使用嵌套LINQ的解决方案,更容易理解。

使用 Linq to Xml。 支持不同的分隔符(const) 支持每一行有不同的切片

input.csv的内容:

A,B,C
D,E,F
G,H

流程代码:

Program.cs

using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;

namespace CSVtoXML

    class Program
    
        private static void AddContentForEachLine(string line, ref XElement xmlTree)
        
            var currentTree = new XElement("Item");
            const string delimiter = ",";     // Can be changed based on the actual situation
            string[] slices = line.Split(delimiter);

            for (int i = 0; i < slices.Count(); i++)
                currentTree.Add(new XElement($"Columni", slices[i].ToString()));

            xmlTree.Add(currentTree);
        

        static void Main(string[] args)
        
            var basePath = Environment.CurrentDirectory;
            var lines = File.ReadAllLines(Path.Combine(basePath, "../../..", @"input.csv"));

            var xmlTree = new XElement("TopElement");

            foreach (var line in lines)
            
                AddContentForEachLine(line, ref xmlTree);
            

            xmlTree.Save(Path.Combine(basePath, "../../..", @"output.xml"));
        
    

运行代码后,结果如下:

<?xml version="1.0" encoding="utf-8"?>
<TopElement>
  <Item>
    <Column0>A</Column0>
    <Column1>B</Column1>
    <Column2>C</Column2>
  </Item>
  <Item>
    <Column0>D</Column0>
    <Column1>E</Column1>
    <Column2>F</Column2>
  </Item>
  <Item>
    <Column0>G</Column0>
    <Column1>H</Column1>
  </Item>
</TopElement>

可以在此处查看此代码的完整 Visual Studio 解决方案: https://github.com/yanglr/dotnetInterview/tree/master/CSVtoXML.

【讨论】:

以上是关于将 CSV 文件转换为 XML的主要内容,如果未能解决你的问题,请参考以下文章

在python中使用argparse将csv转换为xml

将 CSV 转换为 XML

将 .CSV 文件转换为 .XML 的 PHP 脚本

使用 java 将 XML 文件转换为 CSV 文件

powershell 将CSV文件转换为XML

python [xml文件到voc的csv文件]将voc标签转换为xml格式为csv格式#python #csv #xml