Convert XML to csv in c# with multiple collection - c#

I am looking for a way to convert an xml stream to csv, but I only find solution for 1 collection, i.e. my xml looks like :
<?xml version="1.0" encoding="UTF-8"?>
<CompactData>
<Header>
<ID>id_ofç=_file</ID>
<Test>false</Test>
</Header>
<data:DataSet>
<data:Series FREQ="M" item="item1" unit="unit1">
<data:Obs TIME_PERIOD="2015-01" OBS_VALUE="5.47" />
<data:Obs TIME_PERIOD="2015-02" OBS_VALUE="5.01" />
<data:Obs TIME_PERIOD="2015-03" OBS_VALUE="5.39" />
</data:Series>
<data:Series FREQ="M" item="item2" unit="unit2">
<data:Obs TIME_PERIOD="2015-01" OBS_VALUE="5.47" />
<data:Obs TIME_PERIOD="2015-02" OBS_VALUE="5.01" />
<data:Obs TIME_PERIOD="2015-03" OBS_VALUE="5.39" />
</data:Series>
</data:DataSet>
</CompactData>
Here I want a csv with the format :
FREQ,item,unit,TIME_PERIOD,OBS_VALUE
what is the best way to do that?
Thanks!

Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication166
{
class Program
{
const string XML_FILENAME = #"c:\temp\test.xml";
const string CSV_FILENAME = #"c:\temp\test.csv";
static void Main(string[] args)
{
StreamWriter writer = new StreamWriter(CSV_FILENAME);
writer.WriteLine(string.Join(",", new string[] {"FREQ","item","unit","TIME_PERIOD","OBS_VALUE"}));
XDocument doc = XDocument.Load(XML_FILENAME);
XElement dataSet = doc.Descendants().Where(x => x.Name.LocalName == "DataSet").FirstOrDefault();
XNamespace nsData = dataSet.GetNamespaceOfPrefix("data");
foreach (XElement series in dataSet.Elements(nsData + "Series"))
{
string freq = (string)series.Attribute("FREQ");
string item = (string)series.Attribute("item");
string unit = (string)series.Attribute("unit");
foreach (XElement obs in series.Elements(nsData + "Obs"))
{
DateTime time = DateTime.ParseExact((string)obs.Attribute("TIME_PERIOD"), "yyyy-MM", System.Globalization.CultureInfo.InvariantCulture);
double value = (double)obs.Attribute("OBS_VALUE");
writer.WriteLine(string.Join(",", new string[] {freq, item, unit,time.ToString(), value.ToString()}));
}
}
writer.Flush();
writer.Close();
}
}
}

Related

Filter Attributes in Xml in c# AND modify the Xml

I am trying to convert and Xml A into Xml B using C#.
XML A
<root>
<country>
<city name="Boston" value="100">
<city name="Boston" value="200">
</country>
</root>
XMl B(Expected)
<root>
<country>
<city name="Boston" value="300">
</country>
</root>
C# code:
var doc = XDocument.Load(path);
var myDocument = new XmlDocument();
myDocument.Load(path);
var nodes = myDocument.GetElementsByTagName("city");
var resultNodes = new List<XmlNode>();
foreach (XmlNode node in nodes)
{
if (node.Attributes != null && node.Attributes["name"] != null && node.Attributes["name"].Value == "Boston")
resultNodes.Add(node);
foreach(var elements in resultNodes)
{
elements.Attributes.RemoveNamedItem("Boston");
}
}
Basically what i wanted to do here is add the 2 values(100 &200)from 2 different Boston attributes from XML A and print into a new XML B file but lost a bit here as what goes into this block.
foreach (XmlNode i in resultNodes)
{
}
Problems like this is easy to create new XElements. See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<XElement> countries = doc.Descendants("country").ToList();
foreach (XElement oldCountry in countries)
{
XElement newCountry = new XElement("country");
var cities = oldCountry.Elements("city").GroupBy(x => (string)x.Attribute("name"));
foreach (var city in cities)
{
newCountry.Add(new XElement("city", new object[] { new XAttribute("name", city.Key), new XAttribute("value", city.Sum(x => (int)x.Attribute("value"))) }));
}
oldCountry.ReplaceWith(newCountry);
}
}
}
}

How to read XML child node element attributes in each iteration c#?

<?xml version="1.0" encoding="utf-8" ?>
<Checkplan>
<masters>
<sections>
<characteristics>
<characterstic name="xxx1">
</characterstic>
<characterstic name="xxx2">
</characterstic>
<image id="xxx"></image>
</characteristics>
</sections>
<sections>
<characteristics>
<characterstic name="yyy1">
</characterstic>
<characterstic name="yyy2">
</characterstic>
<image id="yyy"></image>
</characteristics>
</sections>
</masters>
</Checkplan>
Image id xxx is common for xxx1 and xxx2 .
Image id yyy is common for yyy1 and yyy2 so i need to loop through only xxx related attributes from first iteration then i have
to read yyy reated in next iteration .
Iteration should run for each section .
XmlNodeList dataNodes = xml.SelectNodes("//Section");
foreach (XmlNode node in dataNodes)
{
foreach (XmlNode childNode in node.ChildNodes)
{
foreach (XmlNode childNode2 in childNode.ChildNodes)
{
FeatureName = childNode2.Attributes["Name"].Value;
LSL = Convert.ToInt32(childNode2.Attributes["LSL"].Value);
USL = Convert.ToInt32(childNode2.Attributes["USL"].Value);
}
}
if (!FeaturesCollection.ContainsKey(FeatureName))
{
FeaturesCollection.Add(FeatureName, new Features { m_Name = FeatureName, m_LSL = LSL, m_USL = USL, m_ImageID = imageid });
}
Using xml linq. You left an 'i' out of characteristic in the xml file. See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("characteristics").Select(x => new {
id = (string)x.Element("image").Attribute("id"),
characteristics = x.Elements("characteristic").ToList().Select(y => (string)y.Attribute("name")).ToList()
}).ToList();
}
}
}

MVC best way to parse MySQL XML Table Export

I am looking for a solution that help me to read fast an XML DataBase Export file,
what looks like this :
<?xml version="1.0" encoding="utf-8"?>
<database name="backup_db">
<table name="users">
<column name="username">user1</column>
<column name="password">pass1</column>
<column name="email">email1</column>
<column name="regdate">2015-01-22 23:31:59</column>
<column name="lastlogin">2016-12-11 01:56:24</column>
<column name="banned">0</column>
</table>
<table name="users">
...
</table>
...
200000 table rows
</database>
I make an solution that enumerate all the element and store the column Value, but have a long execution.
var xd = new XmlDocument();
string path = Server.MapPath("~/App_Data/users.xml");
var fs = new FileStream(path, FileMode.Open);
xd.Load(fs);
var list = xd.GetElementsByTagName("table");
for (var i = 0; i < list.Count; i++)
{
...
}
fs.Close()
Whot to make that work faster ?
Try following. It only adds data as string and will only work if the columns are always in the same order (no skipped columns)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
if (reader.Name != "database")
{
reader.ReadToFollowing("database");
}
reader.MoveToFirstAttribute();
string databaseName = reader.Value;
DataSet ds = new DataSet(databaseName);
DataTable dt = null;
while (!reader.EOF)
{
if (reader.Name != "table")
{
reader.ReadToFollowing("table");
}
if (!reader.EOF)
{
XElement table = (XElement)XElement.ReadFrom(reader);
string tableName = (string)table.Attribute("name");
if (!ds.Tables.Contains(tableName))
{
dt = new DataTable(tableName);
ds.Tables.Add(dt);
dt.Columns.AddRange(table.Elements("column").Select(x => new DataColumn((string)x.Attribute("name"))).ToArray());
}
DataRow newRow = ds.Tables[tableName].Rows.Add();
newRow.ItemArray = table.Elements("column").Select(x => (string)x).ToArray();
}
}
}
}
}

get information from xml node using agsxmpp library

<query xmlns="urn:xmpp:dialogueHistory">
<dialogueHistory id="4d38f289-9">
<MessageID>26164</MessageID>
<messageText>Fhh</messageText>
<msgDate>11/25/2016 6:30:39 AM</msgDate>
<unReadCount>0</unReadCount>
</dialogueHistory>
</query>
get information of messageid,messagetext
how can I get the information from the above xml using agsxmpp library
namespace is agsXMPP.Xml.Dom
You need to specify the namespace. Using xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<XElement> dialogueHistory = doc.Descendants().Where(x => x.Name.LocalName == "dialogueHistory").ToList();
XNamespace ns = dialogueHistory.FirstOrDefault().GetDefaultNamespace();
var results = dialogueHistory.Select(x => new {
id = (string)x.Attribute("id"),
messageId = (int)x.Element(ns + "MessageID"),
messageText = (string)x.Element(ns + "messageText"),
messageDate = (DateTime)x.Element(ns + "msgDate"),
unReadCount = (int)x.Element(ns + "unReadCount")
}).ToList();
}
}
}

Reading XML and Save into Excel C#

I having XML as follow and I need to read this XML and get specific element in the XML and save into excel.
Below is my XML File :
<?xml version="1.0" encoding="UTF-8"?>
<ns1:BookTestXMLExport StartTime="2016-09-20T12:58:15.000+07:00" scanTime="2016-09-20T12:58:15.000+07:00" scanStatus="Pass">
<ns1:MachineXML barCode="ISN-1000500213" Revision="2016A" bookType="Novel"/>
<ns1:StationXML scannerName="HP4512745" stage="v810"/>
<ns1:ScanXML name="32:2:165:1">
<ns1:IndictmentXML algorithm="NIL" subType="17X8X15MM" imageFileName="175228000_9_0.jpg">
<ns1:BorrowXML packageId="NIL" userId="NIL" name="NIL"/>
<ns1:BookXML name="GrayDay" desc="Love Story"/>
</ns1:IndictmentXML>
</ns1:ScanXML>
<ns1:ScanXML name="35:23:165:1">
<ns1:IndictmentXML algorithm="NIL" subType="17X8X15MM" imageFileName="175228001_9_0.jpg">
<ns1:BorrowXML packageId="NIL" userId="8799" name="Sharon"/>
<ns1:BookXML name="Harry Potter" desc="Magic"/>
</ns1:IndictmentXML>
</ns1:ScanXML>
</ns1:BookTestXMLExport>
Below is the expected result:
Expected Result
Can anyone guide me on this.
Try this to parse file. You still need to save as excel.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication14
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement bookTestXMLExport = doc.Descendants().Where(x => x.Name.LocalName == "BookTestXMLExport").FirstOrDefault();
XNamespace ns = bookTestXMLExport.GetNamespaceOfPrefix("ns1");
var results = doc.Descendants(ns + "BookTestXMLExport").Select(x => new
{
scanStatus = (string)x.Attribute("scanStatus"),
barCode = (string)x.Element(ns + "MachineXML").Attribute("barCode"),
ScanXML = x.Elements(ns + "ScanXML").Select( y => new {
name = (string)y.Descendants(ns + "BookXML").FirstOrDefault().Attribute("name"),
desc = (string)y.Descendants(ns + "BookXML").FirstOrDefault().Attribute("desc")
}).ToList()
}).ToList();
}
}
}

Categories

Resources