Reading data from xml to datatable - c#

My xml
<?xml version="1.0" encoding="utf-8" ?>
<Category>
<Youth>
</Youth>
<GeneralStores>
</GeneralStores>
<Schools>
</Schools>
<Colleges>
</Colleges>
<GovernmentOffices>
</GovernmentOffices>
<Restaurants>
</Restaurants>
<MovieTheatres>
</MovieTheatres>
</Category>
I need data table like
_______________________
Category
__________
Youth
GeneralStores
Schools
Colleges
GovernmentOffices
Restaurants
MovieTheatres
I am binding this datatable to telrik rad grid on need datasource event
here is my .cs code
protected void CategoriesRadGrid_NeedDataSource(object source, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
try
{
//create the DataTable that will hold the data
DataTable CategoryDT = new DataTable("MainCategory");
CategoryDT.Columns.Add("Category", System.Type.GetType("System.String"));
CategoryDT.ReadXml(#"C:\Users\MyID\Documents\Visual Studio 2010\Projects\SomeName\InfoXML\XMLCategory.xml");
}
catch (Exception ex)
{
}
}
Code executes good with no data in data table.
Also tell me How to give file location when file is on servers?
presently I am using my local machine path where the file is located.

use XmlDocument to read your XML
XmlDocument doc= new XmlDocument();
doc.Load("physical path to file.xml");
// doc.LoadXml(stringXml);
DataTable dt = new DataTable();
if(doc.ChildNodes[1]!=null)
dt.Columns.Add(doc.ChildNodes[1].Name); //Assuming you want the rood node to be the only column of the datatable
//iterate through all the childnodes of your root i.e. Category
foreach(XmlNode node in doc.ChildNodes [1].ChildNodes )
{
dt.Rows.Add(node.Name);
}

Try the following:
private static DataTable BuildDataTable(XElement x)
{
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn(x.Name.ToString()));
foreach (var d in x.Descendants())
{
DataRow drow = dt.NewRow();
drow[0] = d.Value;
dt.Rows.Add(drow);
}
return dt;
}
the method will iterate through the xml and create the dataTable. Xelement is part linq and will require .Net framework 4. It represents an XML element.
To call the method :
//this answers your second question,
//use Server.MapPath to find your file.
XElement x = XElement.Load(Server.MapPath(".") + #"\test.xml");
DataTable dt = BuildDataTable(x);

Related

XML file to DataGridView in C# asp.Net

This is the XML file I'm trying to fill the DataGridView with:
<?xml version="1.0" encoding="utf-8"?>
<Transactions>
<Transaction>
<Name>David</Name>
<Amount>123</Amount>
<Date>11/11/2011</Date>
</Transaction>
<Transaction>
<Name>Mark</Name>
<Amount>400</Amount>
<Date>12/12/2012</Date>
</Transaction>
<Transaction
><Name>Norah</Name>
<Amount>400</Amount>
<Date>12/12/2012</Date>
</Transaction>
<Transaction>
<Name>Cecil</Name>
<Amount>400</Amount>
<Date>12/12/2012</Date>
</Transaction>
</Transactions>
This is the last code I tried, but it did not work.
Its C# asp.Net ( input array is more than number of columns I only have 3 columns (Name, Amount and Date)
DataTable dt = new DataTable();
XDocument doc = XDocument.Load(filepath);
foreach (XElement transactions in doc.Descendants().Where(x => x.Name.LocalName == "Transactions")){
XElement Name = transactions.Descendants("Name").FirstOrDefault();
XElement Amount = transactions.Descendants("Amount").FirstOrDefault();
XElement date = transactions.Descendants("Date").FirstOrDefault();
dt.Rows.Add(new object[]
{
(string)Name.Element("Name"),
(string)Amount.Element("Amount"),
(string)date.Element("Date")
});
}
dataGridView1.DataSource = dt;
There are a few problems with the posted code.
First, the “newly” created DataTable dt … is never given any columns. Therefore, it is not surprising to see the line of code… dt.Rows.Add(… crash and burn. Hence the current error. Adding the three lines of code below should solve this missing column error.
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Amount", typeof(string));
dt.Columns.Add("Date", typeof(string));
Unfortunately fixing this issue will only reveal another problem…
The foreach loop is grabbing the XML “elements” improperly. I am guessing there is an easier way to do this however, using the posted XML file and taking a closer look at the foreach loop code below…
foreach (XElement transactions in doc.Descendants().Where(x => x.Name.LocalName == "Transactions")) { … }
I am guessing you want to change the string "Transactions" to "Transaction" without the “s.” Leaving the “s” in the string is going to pick up the “whole” XML file since "Transactions" is the root. Therefore, the code will need further clarification as “which” “Name, Amount or Date” to use since there is more than one (1). In addition, the loop will only execute “once” since it is grabbing the root node. I recommend changing the value to "Transaction" to get what you are looking for.
Lastly, the code appears to be overly complicating things when grabbing the XElement value. As discussed above, we now know that we need to change the looping XElement variable to “Transaction,” this will mean that each “element” we get in the loop will look like…
<Transaction>
<Name>David</Name>
<Amount>123</Amount>
<Date>11/11/2011</Date>
</Transaction>
Therefore… if we have an XElement called transaction like above, then a simple assignment…
string Name = Transaction.Element("Name").Value
should return the value we are looking for. It appears unnecessary to create the extra XElement variables (Name, Amount and date). The needed XElement already exist and it is called “transaction.” Given this, the code below should work as expected.
foreach (XElement transaction in doc.Descendants().Where(x => x.Name.LocalName == "Transaction")) {
dt.Rows.Add(transaction.Element("Name").Value, transaction.Element("Amount").Value, transaction.Element("Date").Value);
}
With that said, the code below demonstrates what is described above.
try {
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Amount", typeof(string));
dt.Columns.Add("Date", typeof(string));
XDocument doc = XDocument.Load(filepath);
foreach (XElement transaction in doc.Descendants().Where(x => x.Name.LocalName == "Transaction")) {
dt.Rows.Add(transaction.Element("Name").Value, transaction.Element("Amount").Value, transaction.Element("Date").Value);
}
dataGridView1.DataSource = dt;
}
catch (Exception ex) {
MessageBox.Show("Error: " + ex.Message);
}
It should also be noted that when the code uses the line below…
transaction.Element("NodeName").Value
If “NodeName” does not exist, there is NO exception thrown, it will simply return null. Therefore, if you see the correct number of rows but missing data, it would be wise to check what is returned when reading from the XElement. Hope that helps.
Try this code
using System.Xml;
XmlReader xmlFile = XmlReader.Create(#"C:\Users\Shubham\Documents\Visual Studio 2012\Projects\WindowsFormsApplication1\WindowsFormsApplication1\XMLFile1.xml", new XmlReaderSettings());
DataSet dataSet = new DataSet();
//Read xml to dataset
dataSet.ReadXml(xmlFile);
//Pass Transaction table to datagridview datasource
dataGridView1.DataSource = dataSet.Tables["Transaction"];
//Close xml reader
xmlFile.Close();

Displaying XML data selected from Combobox in Textbox C#

Hello I'm learning C# and I'm trying to show xml information from within User1.xml in a Textbox on the same form after it has been selected in the combobox.
I have managed to populate the combobox with the name tag using this code. (So that a username may be selected)
private void Form1_Load(object sender, EventArgs e)
{
XmlDocument sFor = new XmlDocument();
sFor.Load(Path.GetFullPath("User1.xml"));
XmlNodeList SearchList = sFor.SelectNodes("employee/user/name");
foreach (XmlNode Search in SearchList)
{
comboBox1.Items.Add(Search.InnerText);
}
}
The XML is formatted thusly
<employee>
<user>
<name>John Smith</name>
<department>PAI</department>
<manager>MD</manager>
<hours>full-time</hours>
<leave>940</leave>
</user>
</employee>
How would I (Using linq or xmlreader or otherwise) after selection in the Combobox, display the information in textBox2?
Thank you.
I did something similar with a DataGridView looking for a "City". The input field was Textbox1.Text. I hope this isnt overkill. The credit goes to the posters here at Stack for showing me how to do this! I pulled the specific data first, then load it to a List. lastly, made the List the data source for DGV. That might work for a combo box...yes?
<TaxTbl>
<TaxSite>
<Location>Axx</Location>
<Address>xxx</Address>
<City>aaa</City>
<State> st</State>
<Zip>xxx</Zip>
</TaxSite>
<TaxSite>
<Location>Bxxx</Location>
<Address>xxx</Address>
<City>xxx</City>
<State> st</State>
<Zip>xxx</Zip>
</TaxSite>
</TaxTbl>
var xdoc = XDocument.Load("C:\\Users\\Harley\\desktop\\outfile.xml");
var NewDoc = new XDocument(new XElement("TaxTbl",
from anEntry in xdoc.Element("TaxTbl").Elements("TaxSite")
where anEntry.Element("City").Value.Contains(textBox1.Text)
select anEntry));
var MyList =
(from bEntry in NewDoc.Descendants("TaxSite")
select new
{
Location = bEntry.Element("Location").Value,
Address = bEntry.Element("Address").Value,
City = bEntry.Element("City").Value,
State = bEntry.Element("State").Value,
Zip = bEntry.Element("Zip").Value
}).ToList();
cityDGV.DataSource = MyList.ToList();
If this can help you
XDocument doc = XDocument.Load(Path.GetFullPath("User1.xml"));
var rows = doc.Descendants("employee").Descendants("user").Select(el => new()
{
department = el.Element("department").Value,
manager = el.Element("manager").Value,
hours = el.Element("hours").Value,
leave = el.Element("leave").Value,
});
OR from DataSet like this
DataSet ds = new DataSet();
ds.ReadXmlSchema(new StreamReader("User1.xml"));
ds.ReadXml(new StreamReader("User1.xml"));

XML with several levels to Dataset with XmlDocument

I have this xml file with several levels for node's childs:
-product
--name
--price
--made
-----product
--------name
--distributor
-----name
------address
/product
I need to read it in sequence, but it's not possible with XmlReader, so I have to use XmlDocument to read each node and copy into DataSet (or similar).
How can I read node by node and copy to dataset in C# ??? Any help please?
Convert xml string to DataSet using StringReader
string xmlData = "<product><name></name><price></price><made></made></product>";
StringReader reader = new StringReader(xmlData);
DataSet ds = new DataSet();
ds.ReadXml(reader);
Write XML Data into a DataSet directly from xml file:
string myfile = #"C:\myXml.xml";
DataSet ds = new DataSet();
ds.ReadXml(myfile);
I think you can use Xpath over XMl Document to read node by node.
It is possible using XDocument and LINQ-to-XML:
XDocument doc = XDocument.Load("test.xml");
// Create two DataTable instances.
DataTable table1 = new DataTable("patients");
table1.Columns.Add("name");
foreach(var name in doc.Root.DescendantNodes().OfType<XElement>()
.Select(x => x.Name).Distinct())
{
table1.Rows.Add(name);
Console.WriteLine(name);
}

Read xml string into dataset

I'm getting xml content from a web api. The xml content is a datatable which was converted to xml in the controller and returned as a string.
I try to read it back in a dataset as follows:
var results = response.Content.ReadAsStringAsync().Result;
DataTable dt = new DataTable();
byte[] xmlBytes = Encoding.UTF8.GetBytes(results);
using (DataSet ds = new DataSet())
using (MemoryStream ms = new MemoryStream(xmlBytes))
{
ds.ReadXml(ms);
dt = ds.Tables[0];
}
However is dataset is empty.
The web api controller action does the following:
string xml = string.Empty;
using (DataTable dt = GetResultsAsDataTable())
{
if (dt != null)
{
using (StringWriter sw = new StringWriter())
{
dt.WriteXml(sw, true);
xml = sw.ToString();
}
}
}
The string looks like this:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/"><DocumentElement>
<tablename>
<id>734</id>
<name>734</name>
</tablename>
</DocumentElement></string>
Is it normal that the xml string looks like this?
Absolutely not.
You should fix results first:
results = System.Web.HttpUtility.HtmlDecode(results);
Then, results will look like this:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/"><DocumentElement>
<tablename>
<id>734</id>
<name>734</name>
</tablename>
</DocumentElement></string>
I think you shall make your controller action return a datatable object, then the Web API framework will convert it to XML automatically by default, but the XML maybe hard to read.
here is the code I tried,C# Code,returned XML

Writing XML from a hashtable converted to a table object then loaded to a dataset

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
<blog>
<Title xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Testing this XML File</Title>
<Name xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Shawn</Name>
<Image xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Hosting\html\blogimage\</image>
<Comment xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Shawn is testing this file</Comment>
</blog>
</NewDataSet>
When I am using a Dataset Writexml Method I keep getting this xml file type, I want my XML file to look like this:
<NewDataSet>
<blog>
<Title>Testing this XML File</Title>
<Name>Shawn</Name>
<Image>Hosting\html\blogimage\</image>
<Comment>Shawn is testing this file</Comment>
</blog>
</NewDataSet>
This xml is for a blog with a path to the image file so when the blog loades it will load the image
I want to know will the first xml in the naming tags be effected when I want to call the xml tags for reading the xml file with the w3c links in the tags need to understand why they are writing like this from a dataset it never done that before.
This is the code before the xml is written: Sample
public void WriteDataXml(string name, string title, string comment, string path)
{
DataSet ds = new DataSet();
//Sets the data in the hashtable to write new file
Hashtable lines = new Hashtable();
lines["Name"] = name;
lines["Title"] = title;
lines["Comment"] = comment;
lines["image"] = path;
//Convert hash table to data table
//create an instance of DataTable
var dataTable = new DataTable(lines.GetType().Name);
//specify the table name
dataTable.TableName = "blog";
//fill the columns in the DataTable
foreach (DictionaryEntry entry in lines)
{
dataTable.Columns.Add(entry.Key.ToString(), typeof(object));
}
//create a new DataRow in the DataTable
DataRow dr = dataTable.NewRow();
//fill the new row in the DataTable
foreach (DictionaryEntry entry in lines)
{
dr[entry.Key.ToString()] = entry.Value.ToString();
}
//add the filled up row to the DataTable
dataTable.Rows.Add(dr);
//Appending To Existing: Pass values to the dataset to write the xml file from the hash table
// Add Table to dataset ds
ds.Tables.Add(dataTable);
//Reading Existing: Also include current files from the xml in the data set by reading and current
//Write XML
string filename = Server.MapPath(#".\blog\") + "comments.xml";
ds.WriteXml(filename);
}
Instead of all your code you can create xml with Linq to Xml:
public static void WriteDataXml(
string name, string title, string comment, string path)
{
XDocument xdoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Blog",
new XElement("Title", title),
new XElement("Name", name),
new XElement("Image", path),
new XElement("Comment", comment)));
string filename = Server.MapPath(#".\blog\") + "comments.xml";
xdoc.Save(filename);
}
Output (I think NewDataSet element is not necessary here):
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Blog>
<Title>Testing this XML File</Title>
<Name>Bob</Name>
<Image>Hosting\html\blogimage\</Image>
<Comment>Shawn is testing this file</Comment>
</Blog>

Categories

Resources