简体   繁体   中英

How to convert XML to CSV (C#)

XML:

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <Company>
    <Title>Seph</Title>
    <Commentary>blah-blah</Commentary>
    <Worker1>Bill</Worker1>
    <Worker2>Fill</Worker2>
  </Company>
  <JobDetails>
    <JobNum>1</JobNum>
    <Detail1>Sport</Detail1>
    <Detail2>Physical</Detail2>
  </JobDetails>
  <JobDetails>
    <JobNum>2</JobNum>
    <Detail1>Mailman</Detail1>
    <Detail2>pastoral</Detail2>
  </JobDetails>
  <JobDetails />
</NewDataSet>

I have an example of code converter (XML to CSV) but it works without headlines "Company" and "JobDetails". I need this headlines, can you help me to improve this code?

using System;
using System.Text;
using System.IO;
using System.Xml.Linq;
using System.Linq;
namespace XML_CSV
{
    class Class1
    {
        static void Main()
        {
            StringBuilder sb = new StringBuilder();
            string delimiter = "|";

            XDocument.Load(@"C:\Users\Iuser\Desktop\Data.xml").Descendants("NewDataSet").ToList().ForEach(element => sb.Append(
                            element.Element("Company").Value + delimiter +  //something maybe bad here
                            element.Element("Title").Value + delimiter +
                            element.Element("Commentary").Value + delimiter +
                            element.Element("Worker1").Value + delimiter +
                            element.Element("Worker2").Value + delimiter +
                             element.Element("JobDetails").Value + delimiter + //something maybe bad here
                             element.Element("Detail1").Value + delimiter +
                             element.Element("Detail2").Value + "\r\n"));
            StreamWriter sw = new StreamWriter(@"C:\Users\Iuser\Desktop\DataCSV.csv");
            sw.WriteLine(sb.ToString());
            sw.Close();

        }
    }
}

Possibly code don't work because visual thinks that "Company" and "JobDetails" it's different Tables. This is should look like this (In CSV of cours): Company JobDetails

It should be in one CSV file.

Output text:

Title,Commentary,Worker1,Worker2
Seph,blah-blah,Bill,Fill
JobNum,Detail1,Detail2
1,Sport,Physical
2,Mailman,pastoral

By using XSLT.

XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/NewDataSet">
        <xsl:text>Title,Commentary,Worker1,Worker2</xsl:text>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="Company"/>
        <xsl:text>JobNum,Detail1,Detail2</xsl:text>
        <xsl:text>&#xA;</xsl:text>
        <xsl:for-each select="JobDetails[*]">
            <xsl:value-of select="concat(JobNum, ',', Detail1, ',', Detail2)"/>
            <xsl:text>&#xA;</xsl:text>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="Company">
        <xsl:value-of select="concat(Title, ',', Commentary, ',', Worker1, ',', Worker2)"/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

c#

void Main()
{
    const string SOURCEXMLFILE = @"e:\Temp\XML_to_CSV\input.xml";
    const string XSLTFILE = @"e:\Temp\XML_to_CSV\process.xslt";
    const string OUTPUTFILE = @"e:\Temp\XML_to_CSV\output.csv";

    try
    {
        XsltArgumentList xslArg = new XsltArgumentList();

        using (XmlReader src = XmlReader.Create(SOURCEXMLFILE))
        {
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(XSLTFILE, new XsltSettings(true, true), new XmlUrlResolver());

            XmlWriterSettings settings = xslt.OutputSettings.Clone();
            settings.IndentChars = "\t";
            // to remove BOM
            settings.Encoding = new UTF8Encoding(false);

            using (XmlWriter result = XmlWriter.Create(OUTPUTFILE, settings))
            {
                xslt.Transform(src, xslArg, result, new XmlUrlResolver());
                result.Close();
            }
        }
        Console.WriteLine("File '{0}' has been generated.", OUTPUTFILE);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

Output

Title,Commentary,Worker1,Worker2
Seph,blah-blah,Bill,Fill
JobNum,Detail1,Detail2
1,Sport,Physical
2,Mailman,pastoral

Well, using XSLT for the xml to csv transformation is one way to do it. Here is one another approach using Cinchoo ETL , an open source library to perform the transformation in native way

StringBuilder csv1 = new StringBuilder();
using (var r = new ChoXmlReader("XmlFile3.xml")
    .WithXPath("/Company")
    )
{
    using (var w = new ChoCSVWriter(csv1)
        .WithFirstLineHeader()
        .UseNestedKeyFormat(false)
        )
        w.Write(r);
}

StringBuilder csv2 = new StringBuilder();
using (var r = new ChoXmlReader("XmlFile3.xml")
    .WithXPath("/JobDetails")
    )
{
    using (var w = new ChoCSVWriter(csv2)
        .WithFirstLineHeader()
        .UseNestedKeyFormat(false)
        )
        w.Write(r);
}

string combinedCSV = csv1.ToString() + Environment.NewLine + csv2.ToString();

Console.WriteLine(combinedCSV);

Output:

Title,Commentary,Worker1,Worker2
Seph,blah-blah,Bill,Fill
JobNum,Detail1,Detail2
1,Sport,Physical
2,Mailman,pastoral

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM