Reputation: 23
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
Upvotes: 0
Views: 498
Reputation: 6326
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
Upvotes: 1
Reputation: 22321
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>
</xsl:text>
<xsl:apply-templates select="Company"/>
<xsl:text>JobNum,Detail1,Detail2</xsl:text>
<xsl:text>
</xsl:text>
<xsl:for-each select="JobDetails[*]">
<xsl:value-of select="concat(JobNum, ',', Detail1, ',', Detail2)"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="Company">
<xsl:value-of select="concat(Title, ',', Commentary, ',', Worker1, ',', Worker2)"/>
<xsl:text>
</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
Upvotes: 2