Read XML with C# and fill List<T> - c#

I have an XML document that contains data about two table.
The structure is like this
<doc>
<table name="ordini">
<row>
<field name="id">0431524493258932</field>
<field name="anno">2018</field>
<field name="att">0000</field>
<field name="cen">01</field>
...
</row>
<row>
<field name="id">1041524493596749</field>
<field name="anno">2018</field>
<field name="att">0000</field>
<field name="cen">01</field>
...
</row>
...
</table>
<table name="righe">
<row>
<field name="id">0431524493258932</field>
<field name="anno">2018</field>
<field name="att">0000</field>
<field name="cen">4U</field>
....
</table>
<doc>
I am trying this way with first table in XML with a lot of confusion
var doc = XDocument.Load(filename);
var ordcli = doc.Descendants("table")
.Where(i => (string)i.Attribute("name") == "ordini")
.Descendants("row")
.Select(e => e.Elements());
foreach (var item in ordcli)
{
foreach (var i in item)
{
Console.WriteLine(i);
}
}
How can I read every row element and get field name to instantiate my Order class and OrderDetails class?
When I have my List<Order> and List<OrderDetails> filled I can populate relative tables.
I hope I've explained my requirement well.
I've never used XlmReader or Linq2Xml. It's first time.

try following code :
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)
{
new XML_DataSet(FILENAME);
}
}
public class XML_DataSet
{
static DataSet ds = new DataSet();
public XML_DataSet(string filename)
{
XDocument doc = XDocument.Load(filename);
foreach(XElement table in doc.Descendants("table"))
{
ds.Tables.Add(ReadTable(table));
}
}
private DataTable ReadTable(XElement table)
{
DataTable dt = new DataTable();
Boolean first = true;
foreach (XElement xRow in table.Elements("row"))
{
if (first)
{
foreach (XElement field in xRow.Elements("field"))
{
dt.Columns.Add((string)field.Attribute("name"), typeof(string));
}
first = false;
}
DataRow newRow = dt.Rows.Add();
foreach (XElement field in xRow.Elements("field"))
{
newRow[(string)field.Attribute("name")] = (string)field;
}
}
return dt;
}
}
}

Related

Filter XML collection based on child node data in c#

I have following XML collection of students as shown below.
<stdXmlFormat version="1.0">
<students>
<field id="ClassId">CB0012</field>
<field id="ClassName">CBSE-12</field>
<student id="123">
<field id="SFirstNm">Ram</field>
<field id="SLastNm">Raju</field>
<field id="RollNumber">001</field>
</student>
<student id="124">
<field id="SFirstNm">Sita</field>
<field id="SLastNm">M</field>
<field id="RollNumber">002</field>
</student>
<collection id="StudentCollection">
<record>
<field id="StudentId">5094e0ef-c966-484d-9892-e62bd828e7cf</field>
<field id="FirstName">Ram</field>
<field id="LastName">Raju</field>
</record>
<record>
<field id="StudentId">70a0350a-9556-46f6-b089-bebcc278b1c1</field>
<field id="FirstName">Sita</field>
<field id="LastName">M</field>
</record>
</collection>
<collection id="AccountTransactions">
<record>
<field id="Id">62f4181a-5510-4522-a24a-7d3005f2a907</field>
<field id="TransactionType">Fees</field>
<field id="Balance">5000.00</field>
</record>
<record>
<field id="Id">0958d991-c777-46b3-954c-3682ff735bfc</field>
<field id="TransactionType">Fine</field>
<field id="Balance">2000.00</field>
</record>
<record>
<field id="Id">3aadb37d-d066-491f-8525-2e299ad8d88b</field>
<field id="TransactionType">Fees</field>
<field id="Balance">6000.00</field>
</record>
</collection>
<collection id="StudentAccountTransactions">
<record>
<field id="Id">5e7d0c97-8759-4beb-a688-009e23f10590</field>
<field id="StudentId">5094e0ef-c966-484d-9892-e62bd828e7cf</field>
<field id="AccountTransactionsId">62f4181a-5510-4522-a24a-7d3005f2a907</field>
</record>
<record>
<field id="Id">b22bf993-4dc2-49e6-879f-504ca4ec8424</field>
<field id="StudentId">5094e0ef-c966-484d-9892-e62bd828e7cf</field>
<field id="AccountTransactionsId">0958d991-c777-46b3-954c-3682ff735bfc</field>
</record>
<record>
<field id="Id">44641d91-38bf-4e24-895c-20f92f390acf</field>
<field id="StudentId">70a0350a-9556-46f6-b089-bebcc278b1c1</field>
<field id="AccountTransactionsId">3aadb37d-d066-491f-8525-2e299ad8d88b</field>
</record>
</collection>
</students>
</stdXmlFormat>
The students node is the parent node which consists of child nodes as and collections (StudentCollection, AccountTransactions and StudentAccountTransactions).
<stdXmlFormat version="1.0">
<students>
<student></student>
<collection id="StudentCollection"/>
<collection id="AccountTransactions"/>
<collection id="StudentAccountTransactions"/>
</students>
</stdXmlFormat>
students node is containing all the student details such first name,last name, roll number etc(this was an old collection with more information.some attributes i have removed for better reading and understanding)
And same information is available in the new collection StudentCollection but with less data.this collection is having StudentId (a unique guid used for identifying the student in other collections). the only relation with students and StudentCollection is the student first name and last name.
The AccountTransactions is the collection which holds id (a unique guid for identifying each transactions) and other transaction details. The id in this collection used as AccountTransactionsId in the StudentAccountTransactions collection.
The final collection StudentAccountTransactions which holds the studentid (from StudentCollection) and AccountTransactionsId (from AccountTransactions collection).
So from this list i need to get the details of the students and pass it to DB TEAM for saving to database.They are ready with table structure as shown below
Basically i need to fetch the SFirstNm,SLastNm,RollNumber( from student), StudentId,AccountTransactionsId and StudentAccountTransactionsId from this collection.
I have tried to get the data using XMLdocument and Xdocument but nothing worked
string xpath = #"/stdXmlFormat/students/students/field";
XmlNodeList nodeListstudent = root.SelectNodes(xpath);
foreach (XmlNode item in nodeListstudent )
{
string SID = item.Attributes["id"].Value;
string sFirstNm, sLastNm = string.Empty;
foreach (XmlNode childNodes in item .ChildNodes)
{
string NodeName = childNodes.Attributes["id"].Value;
string NodeValue = childNodes.InnerText;
if (NodeName == "sFirstNm")
{
sFirstNm= NodeValue;
}
if (NodeName == "aBLastNm")
{
sLastNm = NodeValue;
}
}
}
From this i was able to get the student first name and last names etc but how i can fetch the student id from StudentCollection using first name and last name? i am really stuck here please help. with that studentid i need to get other details such as AccountTransactionsId and StudentAccountTransactionsId.
I tried to filter the studentid collections using following way for testing purpose but not worked.
XmlNodeList nodes = jsonXmlDocument.SelectNodes("//stdXmlFormat/students/collection/record/field[#id='5094e0ef-c966-484d-9892-e62bd828e7cf']");
Please help me !
Here is a start :
using System;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApp2
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("StudentId", typeof(string));
dt.Columns.Add("SFirstNm", typeof(string));
dt.Columns.Add("SLastNm", typeof(string));
dt.Columns.Add("RollNumber", typeof(string));
dt.Columns.Add("AccountTransaction", typeof(string));
dt.Columns.Add("StudentAccountTransaction", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
XElement xStudents = doc.Descendants("students").FirstOrDefault();
var students = xStudents.Elements("student")
.Select(x => new
{
id = (string)x.Attribute("id"),
sFName = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "SFirstNm").FirstOrDefault(),
sLName = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "SLastNm").FirstOrDefault(),
rollNumber = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "RollNumber").FirstOrDefault(),
}).ToList();
XElement xStudentCollection = doc.Descendants("collection").Where(x => (string)x.Attribute("id") == "StudentCollection").FirstOrDefault();
var studentCollection = xStudentCollection.Elements("record")
.Select(x => new
{
sId = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "StudentId").FirstOrDefault(),
sFName = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "FirstName").FirstOrDefault(),
sLName = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "LastName").FirstOrDefault(),
}).ToList();
XElement xAccountTransactions = doc.Descendants("collection").Where(x => (string)x.Attribute("id") == "AccountTransactions").FirstOrDefault();
var accountTransactions = xAccountTransactions.Elements("record")
.Select(x => new
{
tId = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "Id").FirstOrDefault(),
type = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "TransactionType").FirstOrDefault(),
balanse = (decimal)x.Elements("field").Where(y => (string)y.Attribute("id") == "Balance").FirstOrDefault(),
}).ToList();
XElement xStudentAccountTransactions = doc.Descendants("collection").Where(x => (string)x.Attribute("id") == "StudentAccountTransactions").FirstOrDefault();
var studentAccountTransactions = xStudentAccountTransactions.Elements("record")
.Select(x => new
{
satId = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "Id").FirstOrDefault(),
sId = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "StudentId").FirstOrDefault(),
tId = (string)x.Elements("field").Where(y => (string)y.Attribute("id") == "AccountTransactionsId").FirstOrDefault(),
}).ToList();
var studentRoll = students.Select(s => studentCollection.Where(sc => (s.sFName == sc.sFName) && (s.sLName == sc.sLName))
.Select(x => new { fName = s.sFName, lName = s.sLName, roll = s.rollNumber, sId = x.sId }).FirstOrDefault()).ToList();
var tranactions = accountTransactions.Select(at => studentAccountTransactions.Where(act => at.tId == act.tId)
.Select(x => new { tId = x.tId, type = at.type, balance = at.balanse, satId = x.satId }).FirstOrDefault()).ToList();
var results = (from sat in studentAccountTransactions
join tr in tranactions on sat.tId equals tr.tId
join sr in studentRoll on sat.sId equals sr.sId
select new { sr = sr, tr = tr, sat = sat })
.ToList();
foreach(var r in results)
{
dt.Rows.Add(new object[]
{
r.sr.sId,
r.sr.fName,
r.sr.lName,
r.sr.roll,
r.tr.tId,
r.sat.satId
});
}
}
}
}

Iterate through an XML document [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 11 months ago.
Improve this question
What's the efficient way to iterate through this XML document using C#? This document is the result of relationship between two apps.
Hence there is the info for the user, and the info for the request itself.
Thank you in advance.
<?xml version="1.0" encoding="utf-16"?>
<Records count="2">
<Metadata>
<FieldDefinitions>
<FieldDefinition id="1001" name="Request ID" alias="Q_ID" />
<FieldDefinition id="1002" name="User" alias="Target" />
<FieldDefinition id="1003" name="Which item(s) is the access requested for?" alias="Which_items_is_requested" />
<FieldDefinition id="1004" name="Select specific(s) for item1" alias="item1" />
<FieldDefinition id="1005" name="Select specific(s) for item2" alias="item2" />
<FieldDefinition id="1006" name="Select specific(s) for item3" alias="item3" />
<FieldDefinition id="101" name="First Name" alias="First_Name" />
<FieldDefinition id="102" name="Last Name" alias="Last_Name" />
<FieldDefinition id="100" name="Email" alias="Email" />
</FieldDefinitions>
</Metadata>
<LevelCounts>
<LevelCount id="989" count="2" />
<LevelCount id="85" count="2" />
</LevelCounts>
<Record contentId="1092725" levelId="989" moduleId="564">
<Record contentId="736205" levelId="85" moduleId="84">
<Field id="100" type="1">john.smith#abc.com</Field>
<Field id="101" type="1">John</Field>
<Field id="102" type="1">Smith</Field>
</Record>
<Field id="1003" type="4">
<ListValues>
<ListValue id="11" displayName="Issues Management">item1</ListValue>
<ListValue id="13" displayName="Master Control Procedures">item3</ListValue>
</ListValues>
</Field>
<Field id="1001" type="6">123123</Field>
<Field id="1002" type="9">
<Reference id="736205">John Smith</Reference>
</Field>
<Field id="1005" type="9">
<Reference id="3">item11</Reference>
<Reference id="3">item12</Reference>
</Field>
<Field id="1006" type="9" />
<Field id="1004" type="9">
<Reference id="7">item31</Reference>
<Reference id="8">item32</Reference>
</Field>
</Record>
<Record contentId="1092759" levelId="989" moduleId="564">
<Record contentId="775678" levelId="85" moduleId="84">
<Field id="100" type="1">Peter.Smith#abc.com</Field>
<Field id="101" type="1">Peter</Field>
<Field id="102" type="1">Smith</Field>
</Record>
<Field id="1003" type="4">
<ListValues>
<ListValue id="11" displayName="Issues Management">item1</ListValue>
<ListValue id="12" displayName="Master Control Procedures">item2</ListValue>
<ListValue id="13" displayName="Control Procedure">item3</ListValue>
</ListValues>
</Field>
<Field id="1001" type="6">123124</Field>
<Field id="1002" type="9">
<Reference id="775678">Peter Smith</Reference>
</Field>
<Field id="1005" type="9">
<Reference id="3">item11</Reference>
<Reference id="4">item12</Reference>
</Field>
<Field id="1006" type="9">
<Reference id="5">item21</Reference>
<Reference id="6">item22</Reference>
</Field>
<Field id="1004" type="9">
<Reference id="7">item31</Reference>
<Reference id="8">item32</Reference>
</Field>
</Record>
</Records>
What's the efficient way to iterate through this XML document using C#? This document is the result of relationship between two apps.
Hence there is the info for the user, and the info for the request itself.
Thank you in advance.
From the comments, your question is how you deserialize the nested records.
A class structure like this seems to work:
public class Records
{
[XmlElement("Record")]
public List<Record> Items { get; } = new();
}
public class Record
{
[XmlAttribute("contentId")]
public int ContentId { get; set; }
[XmlElement("Record")]
public Record ChildRecord { get; set; }
[XmlElement("Field")]
public List<Field> Fields { get; } = new();
}
public class Field
{
[XmlAttribute("id")]
public int Id { get; set; }
[XmlElement("Reference")]
public List<Reference> References { get; } = new();
[XmlArray("ListValues")]
public List<ListValue> ListValues { get; } = new();
[XmlText]
public string Content { get; set; }
}
public class Reference
{
[XmlAttribute("id")]
public int Id { get; set; }
}
public class ListValue
{
[XmlAttribute("id")]
public int Id { get; set; }
[XmlText]
public string Content { get; set; }
}
See this doc on how to use the various attributes.
I haven't bothered to deserialize all of the attributes, or the Metadata or LevelCounts sections -- those are an exercise for the reader!
Use an XmlSerializer, for example:
using var reader = new StringReader(input);
var records = (Records)new XmlSerializer(typeof(Records)).Deserialize(reader);
See it on dotnetfiddle.net.
To flatten data into one table is messy but can be done. See below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication21
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
StreamReader sReader = new StreamReader(FILENAME);
//skip 1st line containing UTF-16
sReader.ReadLine();
XDocument doc = XDocument.Load(sReader);
DataTable dt = new DataTable();
dt.Columns.Add("Field Id", typeof(int));
dt.Columns.Add("Field Name", typeof(string));
dt.Columns.Add("Alias", typeof(string));
dt.Columns.Add("Main Content ID", typeof(int));
dt.Columns.Add("Main Level ID", typeof(int));
dt.Columns.Add("Main Module ID", typeof(int));
dt.Columns.Add("Sub Content ID", typeof(int));
dt.Columns.Add("Sub Level ID", typeof(int));
dt.Columns.Add("Sub Module ID", typeof(int));
dt.Columns.Add("Type", typeof(int));
dt.Columns.Add("Field Value Name", typeof(string));
dt.Columns.Add("Field Text", typeof(string));
dt.Columns.Add("List Value Id", typeof(int));
dt.Columns.Add("Display Name", typeof(string));
dt.Columns.Add("List Value Text", typeof(string));
dt.Columns.Add("Reference Id", typeof(int));
dt.Columns.Add("Reference Text", typeof(string));
foreach (XElement fieldDefinition in doc.Descendants("FieldDefinition"))
{
DataRow newRow = dt.Rows.Add();
newRow["Field Id"] = (int)fieldDefinition.Attribute("id");
newRow["Field Name"] = (string)fieldDefinition.Attribute("name");
newRow["Alias"] = (string)fieldDefinition.Attribute("alias");
}
foreach (XElement record in doc.Root.Elements("Record"))
{
int mainContentId = (int)record.Attribute("contentId");
int mainLevelId = (int)record.Attribute("levelId");
int mainModuleId = (int)record.Attribute("moduleId");
foreach(XElement subRecord in record.Elements("Record"))
{
int subContentId = (int)record.Attribute("contentId");
int subLevelId = (int)record.Attribute("levelId");
int subModuleId = (int)record.Attribute("moduleId");
foreach (XElement field in subRecord.Elements("Field"))
{
int fieldId = (int)field.Attribute("id");
int fieldType = (int)field.Attribute("type");
string fieldName = (string)field;
DataRow fieldRow = dt.AsEnumerable().Where(x => x.Field<int>("Field Id") == fieldId).First();
fieldRow["Main Content ID"] = mainContentId;
fieldRow["Main Level ID"] = mainLevelId;
fieldRow["Main Module ID"] = mainModuleId;
fieldRow["Sub Content ID"] = subContentId;
fieldRow["Sub Level ID"] = subLevelId;
fieldRow["Sub Module ID"] = subModuleId;
fieldRow["Type"] = fieldType;
fieldRow["Field Value Name"] = fieldName;
}
foreach (XElement field in record.Elements("Field"))
{
int fieldId = (int)field.Attribute("id");
int fieldType = (int)field.Attribute("type");
string fieldText = (string)field;
int count = 0;
DataRow fieldRow = dt.AsEnumerable().Where(x => x.Field<int>("Field Id") == fieldId).First();
List<XElement> listValues = field.Descendants("ListValue").ToList();
List<XElement> references = field.Elements("Reference").ToList();
if (listValues.Count > 0)
{
foreach (XElement listValue in listValues)
{
count++;
int listValueId = (int)listValue.Attribute("id");
string displayName = (string)listValue.Attribute("displayName");
string listValueText = (string)listValue;
if (count > 1)
{
string fieldName = fieldRow.Field<string>("Field Name");
string alias = fieldRow.Field<string>("Alias");
fieldRow = dt.Rows.Add();
fieldRow["Field Id"] = fieldId;
fieldRow["Field Name"] = fieldName;
fieldRow["Alias"] = alias;
}
fieldRow["Main Content ID"] = mainContentId;
fieldRow["Main Level ID"] = mainLevelId;
fieldRow["Main Module ID"] = mainModuleId;
fieldRow["Type"] = fieldType;
if(fieldText.Length > 0) fieldRow["Field Text"] = fieldText;
fieldRow["List Value Id"] = listValueId;
fieldRow["Display Name"] = displayName;
fieldRow["List Value Text"] = listValueText;
}
}
count = 0;
if (references.Count > 0)
{
foreach (XElement reference in references)
{
count++;
int referenceId = (int)reference.Attribute("id");
string referenceText = (string)reference;
if (count > 1)
{
string fieldName = fieldRow.Field<string>("Field Name");
string alias = fieldRow.Field<string>("Alias");
fieldRow = dt.Rows.Add();
fieldRow["Field Id"] = fieldId;
fieldRow["Field Name"] = fieldName;
fieldRow["Alias"] = alias;
}
fieldRow["Main Content ID"] = mainContentId;
fieldRow["Main Level ID"] = mainLevelId;
fieldRow["Main Module ID"] = mainModuleId;
fieldRow["Type"] = fieldType;
if (fieldText.Length > 0) fieldRow["Field Text"] = fieldText;
fieldRow["Reference Id"] = referenceId;
fieldRow["Reference Text"] = referenceText;
}
}
if((listValues.Count == 0) && (references.Count == 0))
{
fieldRow["Type"] = fieldType;
if (fieldText.Length > 0) fieldRow["Field Text"] = fieldText;
}
}
}
}
dt = dt.AsEnumerable().OrderBy(x => x.Field<int>("Field Id")).CopyToDataTable();
}
}
}

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);
}
}
}
}

XML to DataTable (list item)

Here is my schema of xml.
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfResultstring xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Resultstring>
<Key>Blablabla : </Key>
<Values>
<string>79,0441326460292</string>
<string>76,0959542079328</string>
<string>74,3061819154758</string>
<string>78,687039788779</string>
</Values>
<Type>list</Type>
</Resultstring>
<Resultstring>
<Key>Blablabla : </Key>
<Values>
<string>87,7110395931923</string>
</Values>
<Type>double</Type>
</Resultstring>
</ArrayOfResultstring>
I need read this XML file and fill the datatable.
I'm trying with DataSet.
DataSet ds = new DataSet();
ds.ReadXml(path);
DataTable dt = ds.Tables[0];
And my output datatable is like.
I need to show my items on table. Is there any way to read properly ?
Try following xml linq which creates a separate row for each string :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication51
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("KEY", typeof(string));
dt.Columns.Add("RESULTING_ID", typeof(string));
dt.Columns.Add("TYPE", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
XElement root = doc.Root;
XNamespace ns = root.GetDefaultNamespace();
foreach (XElement resultingString in doc.Descendants(ns + "Resultstring"))
{
string key = (string)resultingString.Element("Key");
string type = (string)resultingString.Element("Type");
string ids = string.Join(";", resultingString.Descendants("string").Select(x => (string)x));
dt.Rows.Add(new object[] { key, ids, type });
}
}
}
}
Code to put each string in a separate column
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication51
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement root = doc.Root;
XNamespace ns = root.GetDefaultNamespace();
int maxString = doc.Descendants(ns + "Resultstring").Select(x => x.Descendants("string").Count()).Max();
DataTable dt = new DataTable();
dt.Columns.Add("KEY", typeof(string));
dt.Columns.Add("TYPE", typeof(string));
for (int i = 0; i < maxString; i++)
{
dt.Columns.Add("RESULTING_ID_" + (i + 1).ToString(), typeof(string));
}
foreach (XElement resultingString in doc.Descendants(ns + "Resultstring"))
{
string key = (string)resultingString.Element("Key");
string type = (string)resultingString.Element("Type");
List<string> row = resultingString.Descendants("string").Select(x => (string)x).ToList();
row.Insert(0, key);
row.Insert(1, type);
dt.Rows.Add(row.ToArray());
}
}
}
}
With Cinchoo ETL - an open source library, you can easily convert Xml file to DataTable with few lines of code.
For your sample xml file, you can extract the data into datatable as below
using (var p = new ChoXmlReader(** YOUR XML FILE **)
.WithField("Key")
.WithField("Value", xPath: "/Values/string")
)
{
var dt = p.SelectMany(r => ((Array)r.Value).OfType<string>().Select(r1 => new { Key = r.Key, Value = r1})).AsDataTable();
}
Output:
Hope it helps.
your Resultstring xml node is repeating. Below code is working for me
<Resultstring>
<Key>Blablabla : </Key>
<Values>
<string>79,0441326460292</string>
<string>76,0959542079328</string>
<string>74,3061819154758</string>
<string>78,687039788779</string>
</Values>
<Type>list</Type>
<Key>Blablabla : </Key>
<Values>
<string>87,7110395931923</string>
</Values>
<Type>double</Type>
</Resultstring>
Dataset code
DataSet ds = new DataSet();
ds.ReadXml(path);
DataTable dtKey = ds.Tables[0];
DataTable dtValues = ds.Tables[1];
DataTable dtstring = ds.Tables[2];
DataTable dtType = ds.Tables[3];

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();
}
}
}
}
}

Categories

Resources