【问题标题】:Convert Multiple XML files into single CSV using XSLT and C#使用 XSLT 和 C# 将多个 XML 文件转换为单个 CSV
【发布时间】:2014-06-07 22:53:23
【问题描述】:

我正在尝试使用 XSLT 将 XML 文件转换为 CSV。有用。我能够使用 XSLT 转换 XML 并获得我想要的输出。

我现在面临的挑战是我在一个位置有许多 XML 文件。我想从所有 XML 中获取所有数据并将它们放入单个 CSV 文件中。我有一个 for 循环,它遍历文件夹并获取 XML 文件,然后将其导出为 CSV。但是,每次它转换新的 XML 时,它都会覆盖当前 CSV 文件中的数据。所以最终结果是我在 CSV 文件中只得到一行而不是 500 行(如果有 500 个 xml 文件)。

这是 C# 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.IO;
using System.Diagnostics;

namespace XSL
{

class Program
{

    public static void Main(string[] args)
    {
        try
        {
            //declaring xmlFile
            string xmlfile ;

            //Loading the XSLT template
            String xsltfile = "C:\\Win\\XMLReader\\XSL\\csv.xsl";

            //get folder location

            string d = DateTime.Now.ToString("yyyyMMdd");
            //Console.WriteLine(d.ToString());

            //first part of the location path

            String firstPath = @"\\tripx-exportm\\output\\Skill 53115;1_";

            //full path
            string fullPath = firstPath + d.ToString() + "_000000" + @"\\IDX";

            //Get files from a folder

            string[] filePath = Directory.GetFiles(fullPath, "*.xml");

           //get each file in the folder
            foreach (string file in filePath)
            {
                Console.WriteLine(file);
                xmlfile = file;
                Transform(xmlfile, xsltfile);

            }

            //Get the count of XML files in the current folder
            DirectoryInfo dir = new DirectoryInfo(fullPath);
            int count = dir.GetFiles().Length;

            Console.WriteLine("Count of XML files: " + count);


            //Transform(xmlfile, xsltfile);
            Console.WriteLine("press any key");
            Console.ReadKey();
        }
        catch(Exception e){
            Console.WriteLine(e.ToString());
        }

    }

    public static void Transform(string xml, string xslt)
    {
        try
        {
            //load the xml doc

            XPathDocument myDoc = new XPathDocument(xml);

            XslCompiledTransform myXL = new XslCompiledTransform();


            //load the xslt doc
            myXL.Load(xslt);

            //create the output

            XmlTextWriter myWriter = new XmlTextWriter("result.csv", null);

            myXL.Transform(myDoc, null, myWriter);

            myWriter.Close();



        }
        catch (Exception e)
        {
            Console.WriteLine("exception : {0}", e.ToString());
        };
    }

}

}

XSLT file

关于如何将多个 XML 中的数据放入单个 CSV 的任何建议?

谢谢

【问题讨论】:

  • 我说这个问题真的是“如何在使用XmlTextWriter 时附加到文件吗?”
  • 要读取多个文档,请查看document() 函数。您必须想出一些机制(参数、控制文件等)来告诉样式表您要阅读哪些文档。

标签: c# xml xslt csv


【解决方案1】:

您需要为XmTextWriter 使用正确的构造函数重载来获取流,而不是文件名。

MSDN 上的帮助说明了文件名重载:

要写入的文件名。如果文件存在,它会截断它并 用新内容覆盖它。

所以你应该对Transform 执行此操作以使其工作:

public static void Transform(Stream stream, string xml, string xslt)
{
    var myDoc = new XPathDocument(xml);
    var myXL = new XslCompiledTransform();
    myXL.Load(xslt);
    using(var myWriter = new XmlTextWriter(stream, Encoding.Default))
    {
        myXL.Transform(myDoc, null, myWriter);
        myWriter.Flush();
        myWriter.Close();
    }
}

那么调用代码应该是这样的:

using (var fs = new FileStream("result.csv", FileMode.Create))
{
    foreach (string file in filePath)
    {
        Transform(fs, file, xsltfile);
    }
    fs.Flush();
    fs.Close();
}

我已经去掉了(坏的)异常处理和 cmets 等。

【讨论】:

  • 感谢您的回复。添加此代码后,它会为第一个 XML 生成 csv,然后阻塞。 “流不可写”
  • @user1426542 - 尝试取出 myWriter using 语句(只需声明实例)和 myWriter 刷新并关闭。如果它有效,则关闭myWriter 会导致问题。否则,我只会检查您是否按照我所做的相同方式放置所有内容。
【解决方案2】:

我想出了一个不同的方法。这可能不是最好的解决方案,但它对我有用。

在我的代码中,我添加了一个计数器来计算已处理的 XML 数量。它增加。 在我的转换过程中,我没有硬编码名称“result.csv”,而是生成名称:

string Result = "result" + count.ToString() + ".csv";

我在 XMLWriter 中使用该名称

XmlTextWriter myWriter = new XmlTextWriter(Result, null);

这样,它会为每个 XML 生成一个 CSV,并且不会覆盖现有的。

然后我编写了另一个程序,将所有 CVS 合并为一个:

 private static void JoinCsvFiles(string[] csvFileNames, string outputDestinationPath)
    {
        StringBuilder sb = new StringBuilder();

        bool columnHeadersRead = false;

        foreach (string csvFileName in csvFileNames)
        {
            TextReader tr = new StreamReader(csvFileName);

            string columnHeaders = tr.ReadLine();

            // Skip appending column headers if already appended
            if (!columnHeadersRead)
            {
                sb.AppendLine(columnHeaders);
                columnHeadersRead = true;
            }

            sb.AppendLine(tr.ReadToEnd());
        }

        File.WriteAllText(outputDestinationPath, sb.ToString());
    }

总的来说,我只是打电话

string[] csvFileNames = Directory.GetFiles(".", "result*.csv");

        JoinCsvFiles(csvFileNames, "CsvOutput.csv");

希望这对某人有所帮助。

【讨论】:

    猜你喜欢
    • 2018-03-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    相关资源
    最近更新 更多