Saving xml Document into DataTable - c#

Ive got an asp.net page in which im using c# to read an xml document and add each entry into a listview.
I then have the function for the user to add a new entry to the list view but i cant figure out how to save it on a button event.
This is what I have to load the document.
protected void Button6_Click(object sender, EventArgs e)
{
XmlDocument xmlDocument = new XmlDocument();
using (DataTable tabListView1 = new DataTable())
{
tabListView1.Columns.Add("value", Type.GetType("System.String"));
xmlDocument.Load(AppDomain.CurrentDomain.BaseDirectory + "/XmlFile/ListView1.xml");
XmlNodeList xmlNodeList = xmlDocument.SelectNodes("root/data[#open='1']");
foreach (XmlNode xmlNode in xmlNodeList)
{
DataRow dr = tabListView1.NewRow();
dr["value"] = xmlNode.InnerText;
tabListView1.Rows.Add(dr);
}
ListView1.DataSource = tabListView1;
ListView1.DataBind();
}
TextBox3.Text = "Microsoft";
}
How can i make it save changes back to ListView1.xml? Thanks!

Assuming you can get your datasource back as a DataTable from the control you are managing it with, this should help.
private static void SaveXml(string pathAndFileName, DataTable source)
{
XmlDocument xmlDoc = new XmlDocument();
var root = xmlDoc.CreateElement("root");
xmlDoc.AppendChild(root);
foreach (DataRow row in source.Rows)
{
var dataElement = xmlDoc.CreateElement("data");
var openAttribute = xmlDoc.CreateAttribute("open");
openAttribute.Value = "1";
dataElement.Attributes.Append(openAttribute);
dataElement.InnerText = row["value"].ToString();
root.AppendChild(dataElement);
}
xmlDoc.Save(pathAndFileName);
}

Related

updating xmlnodes with foreach loop from datagridview

I'm trying to update an XML node with new data extracted from datagridview.
The issue is that the code below takes only the last values and update it.
For example, I have 2 rows in the grid with arg1 and arg.2 values. When I extract it and iterate/ update the xmlnode, only the last row (row-1) data get updated in the xmlfile and the first one is ignored. Please advise.
public void button2_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
XmlDocument Newdoc = new XmlDocument();
Newdoc.Load(openFileDialog1.FileName);
int r = 0;
foreach (XmlNode updatenode in Newdoc.SelectNodes(".//event[#type='2VO']"))
{
Newdoc.SelectSingleNode(".//#Arg1").InnerText = dataGridView1.Rows[r].Cells["Arg1"].Value.ToString();
Newdoc.SelectSingleNode(".//#Arg2").InnerText = dataGridView1.Rows[r].Cells["Arg2"].Value.ToString();
r++;
}
Newdoc.Save(#"C:\Users\namokhtar\Desktop\updatednew.xml");
}

Filling datatable based on custom XML nodes

i need to show my xml in a gridview using datatable.
My XML is composed in this way:
Click here to see the XML
Now i am getting data in this way:
XmlDocument doc = new XmlDocument();
doc.Load(#"path\MyXml.xml"); //Percorso file xml
DataTable dt = new DataTable();
foreach (XmlNode xns in doc.SelectSingleNode("Settembre"))
{
string tagName = xns.Name;
if (!dt.Columns.Contains(tagName))
{
dt.Columns.Add(tagName);
}
}
With this part of the code i add my columns based on the child tags of "Settembre" (e.g. "ven_01") and this works.
Then i am writing stuff (the innerText of the child tags of the child tags of "Settembre", e.g. "Mattina_Turno_1" in "ven_01") into the cells in this way
DataRow dr = dt.NewRow();
foreach (XmlNode xns in doc.SelectSingleNode("Settembre"))
{
dr[xns.Name] = xns.InnerText;
}
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
And this works too but what i want to do is display a first columns made of the parent node of the innerText as rows name in first column first cell for each row (the max of them are 3, to explain better are the tag "Mattina_Turno1", "Mattina_Turno_2" and "Pomeriggio" , inside them can be some innerText)
This is what i have tried to do for a while.
Also since the rows name are only 3 and the columns name can be more than 3 i'd like to revert them, so, if it is possible, to display the rows name in the columns header(so "Mattina_Turno1", "Mattina_Turno_2" and "Pomeriggio" instead) and as rows name the "Settembre" child tags (e.g. "ven_01").
I hope i made me understandable
Please do not mark as duplicated because i searched a lot on the web and have not found a solution, so please do not downvote and mark as duplicated, it is not.
I found a solution by doing this:
DataTable dt = new DataTable();
dt.Columns.Add("Data");
foreach (XmlNode xns in doc.DocumentElement)
{
if (xns.Name == "Settembre") ///IMPLEMENTARE SELEZIONE AUTOMATICA DEL MESE IMPORTANTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
foreach (XmlNode xn in xns)
{
string tagName = xn.Name;
var a = dt.Rows.Add(tagName);
// int index_of_a = dt.Rows.IndexOf(a);
}
}
dt.Columns.Add("Mattina Turno 1");
dt.Columns.Add("Mattina Turno 2");
dt.Columns.Add("Pomeriggio");
expo_days.DataSource = dt;
expo_days.DataBind();
foreach (XmlNode xns in doc.DocumentElement)
{
if (xns.Name == "Settembre") ///IMPLEMENTARE SELEZIONE AUTOMATICA DEL MESE IMPORTANTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
foreach (XmlNode xn in xns)
{
string tagName = xn.Name;
var a = dt.Rows.Add(tagName);
// int index_of_a = dt.Rows.IndexOf(a);
DataRow[] rows = dt.Select("Data = '"+tagName+"'");
foreach (XmlNode xna in xn)
{ //sistemare le celle in base alla colonna della gridview
if(xna.Name == "Mattina_Turno_1") //here i specify in wich column is the "Mattina_Turno_1" and fill in that cell, and so on
expo_days.Rows[dt.Rows.IndexOf(rows[0])].Cells[3].Text = xna.InnerText;
if (xna.Name == "Mattina_Turno_2")
expo_days.Rows[dt.Rows.IndexOf(rows[0])].Cells[4].Text = xna.InnerText;
if (xna.Name == "Pomeriggio")
expo_days.Rows[dt.Rows.IndexOf(rows[0])].Cells[5].Text = xna.InnerText;
}
}
}

Writing textbox values to xml file in C#.net

I have two TextBoxes namely txtUserid and txtPassowrd.
I'm writing the values entered in textboxes to a XML file but I do not want the same txtuserid values to be written twice in XML - it should be overwritten.
For example :
If I enter in txtUserid=2 and txtPassword=I
and the second time if I enter txtUserid=2 and txtPassword=m
then I only want one entry to be kept in the XML file :
For the above example: the txtUserid=2 and textPassword=m
The code:
XDocument Xdoc = new XDocument(new XElement("Users"));
if (System.IO.File.Exists("D:\\Users.xml"))
{
Xdoc = XDocument.Load("D:\\Users.xml");
}
else
{
Xdoc = new XDocument();
}
XElement xml = new XElement("Users",
new XElement("User",
new XAttribute("UserId", txtUserName.Text),
new XAttribute("Password", txtPassword.Text)));
if (Xdoc.Descendants().Count() > 0)
{
Xdoc.Descendants().First().Add(xml);
}
else
{
Xdoc.Add(xml);
}
Xdoc.Save("D:\\Users.xml");
Search your existing XML document for a node where the UserId attribute matches your current one, and if it does, modify that one, else make a new one.
I'd imagine that your coude would resemble the following:
List<XElement> list = Xdoc.Descendants("User").Where(el => el.Attribute("UserId").Value == txtUserName.Text).ToList();
if (list.Count == 0)
{
// Add new node
}
else
{
// Modify the existing node
}
Edit: In response to your comment, the code to edit your XElement would look something like
string myValue = "myValue";
list.First().Attribute("ElementName").SetValue(myValue);
Writing textbox values to XML file in C#
protected void btnSave_Click(object sender, EventArgs e)
{
// Open the XML doc
System.Xml.XmlDocument myXmlDocument = new System.Xml.XmlDocument();
myXmlDocument.Load(Server.MapPath("InsertData.xml"));
System.Xml.XmlNode myXmlNode = myXmlDocument.DocumentElement.FirstChild;
// Create new XML element and populate its attributes
System.Xml.XmlElement myXmlElement = myXmlDocument.CreateElement("entry");
myXmlElement.SetAttribute("Userid", Server.HtmlEncode(textUserid.Text));
myXmlElement.SetAttribute("Username", Server.HtmlEncode(textUsername.Text));
myXmlElement.SetAttribute("AccountNo", Server.HtmlEncode(txtAccountNo.Text));
myXmlElement.SetAttribute("BillAmount", Server.HtmlEncode(txtBillAmount.Text));
// Insert data into the XML doc and save
myXmlDocument.DocumentElement.InsertBefore(myXmlElement, myXmlNode);
myXmlDocument.Save(Server.MapPath("InsertData.xml"));
// Re-bind data since the doc has been added to
BindData();
Response.Write(#"<script language='javascript'>alert('Record inserted Successfully Inside the XML File....')</script>");
textUserid.Text = "";
textUsername.Text = "";
txtAccountNo.Text = "";
txtBillAmount.Text = "";
}
void BindData()
{
XmlTextReader myXmlReader = new XmlTextReader(Server.MapPath("InsertData.xml"));
myXmlReader.Close();
}

converting xml document to data table in C#

I'm trying to read a simple webservice (REST) and populate a drop down box in my C# desktop application. I;m using .net 2.0
Following is my web service return xml
<sections type="array">
<section>
<name>Standing</name>
<created-at type="datetime">2011-10-23T23:17:54+05:30</created-at>
<updated-at type="datetime">2011-10-23T23:17:54+05:30</updated-at>
<id type="integer">1</id>
<status type="integer">1</status>
<service-charge type="float">0.0</service-charge>
</section>
<section>
<name>VIP</name>
<created-at type="datetime">2011-10-30T11:27:05+05:30</created-at>
<updated-at type="datetime">2011-10-30T11:27:05+05:30</updated-at>
<id type="integer">2</id>
<status type="integer">1</status>
<service-charge type="float">10.0</service-charge>
</section>
and in the following code I'm trying to convert the xml document to a data table
public DataTable getSections() {
String url = "http://<site_url>/sections.xml";
DataTable t = new DataTable();
HttpHandler handle = new HttpHandler();
StreamReader sr = handle.executeGET(url);
String xml = "";
while (sr.Peek() >= 0)
{
xml += sr.ReadLine();
}
XmlDataDocument doc = new XmlDataDocument();
doc.LoadXml(xml);
XmlReader xmlReader = new XmlNodeReader(doc);
DataSet ds = new DataSet();
ds.ReadXml(xmlReader);
t = ds.Tables[0];
return t;
}
and in the last segment I'm trying to bind it to my drop down box (cmbSections)
DataTable t = sec.getSections();
cmbSections.DataSource = t;
cmbSections.DisplayMember = "name";
cmbSections.ValueMember = "id";
But I'm getting the following error
Cannot bind to the new display member.
Parameter name: newDisplayMember
What am i missing here, please help, I'm new to C# world
Use extension method to support conversion of XElement to Datatable. You can add this method to any of your utility classes. Make sure the class is static.
public static class XElementExtensions
{
public static DataTable ToDataTable(this XElement element)
{
DataSet ds = new DataSet();
string rawXml = element.ToString();
ds.ReadXml(new StringReader(rawXml));
return ds.Tables[0];
}
public static DataTable ToDataTable(this IEnumerable<XElement> elements)
{
return ToDataTable(new XElement("Root", elements));
}
}
How to use
//Add logic to store xml data in file or string & read accordingly here.
string file = Server.MapPath("~/Data.xml");
XDocument document = XDocument.Load(file);
var query = from b in document.Elements("sections").Elements("section")
select b;
DataTable table = query.ToDataTable();
Simple way to convert XML to DataSet:
StringReader strr = new StringReader(strXML);
XmlTextReader xtr = new XmlTextReader(strr);
YourTypeDataSet dstest = new YourTypeDataSet();
dstest.ReadXml(xtr);
if (dstest.Tables.Count > 0) ...
for correct conversion, you replace your type DataSet in place of:
DataSet dstest = new DataSet();
;)
I got it working with the following code, but I'm not quit sure if this is the correct way to do it
(This parse the above same xml)
public DataTable getSections() {
String url = "http://<site_url>/sections.xml/sections.xml";
DataTable t = new DataTable();
t.Columns.Add("id", typeof(String));
t.Columns.Add("name", typeof(String));
HttpHandler handle = new HttpHandler();
StreamReader sr = handle.executeGET(url);
String xml = "";
List<String> id = new List<string>();
List<String> name = new List<string>();
while (sr.Peek() >= 0)
{
xml += sr.ReadLine();
}
XmlDataDocument doc = new XmlDataDocument();
doc.LoadXml(xml);
XmlReader xmlReader = new XmlNodeReader(doc);
while (xmlReader.Read()){
if (xmlReader.IsStartElement()) {
String b = xmlReader.Name;
switch (xmlReader.Name) {
case "sections":
break;
case "section":
break;
case "id":
if (xmlReader.Read())
{
id.Add(xmlReader.Value.Trim());
}
break;
case "name":
if (xmlReader.Read())
{
name.Add(xmlReader.Value.Trim());
}
break;
}
}
}
int counter = 0;
foreach (String i in id) {
DataRow r = t.NewRow();
r["id"] = i;
r["name"] = name[counter];
t.Rows.Add(r);
counter += 1;
}
return t;
}
Thanks for the comments :D
Your valuable comments are always welcome

How to generate xml file with specific structure from datatables?

Q :
According to some choices of the user, i will get set of Datatables from the database.
i have three datatabels:Teachers,Subjects,ClassRooms
and I want an xml file with the following structure:
<timetable importtype="database" options="idprefix:id">
<teachers options="" columns="id,name,short">
</teachers>
<subjects options="" columns="id,name,short">
</subjects>
<classrooms options="" columns="id,name,short">
</classrooms>
</timetable>
Now How to generate xml file with the previous structure and fill the xml file data from the data tables?
ex:
<teachers options="" columns="id,name,short">
<teacher id="a" name="jhon" short="jo"/>
<teacher id="b" name="philips" short="Ph"/>
<teacher id="c" name="sara" short="Sa"/>
</teachers>
From teacher datatable.
please details answer with sample example as possible.
EDIT :
private static void ConvertDataTableToXML(string schemaFile, DataTable dtTeacher, DataTable dtSubject, DataTable dtClassRoom)
{
XDocument doc = new XDocument();
//Read the teachers element from xml schema file
XElement teachers = XDocument.Load(schemaFile).Descendants("teachers").SingleOrDefault();
XElement subjects = XDocument.Load(schemaFile).Descendants("subjects").SingleOrDefault();
XElement classes = XDocument.Load(schemaFile).Descendants("classrooms").SingleOrDefault();
if (teachers != null)
{
foreach (DataRow row in dtTeacher.Rows)
{
XElement teacher = new XElement("teacher");
teacher.SetAttributeValue("id", row["id"]);
teacher.SetAttributeValue("name", row["name"]);
teacher.SetAttributeValue("short", row["name"].ToString().Substring(0, 2));
teachers.Add(teacher);
}
}
if (subjects != null)
{
foreach (DataRow row in dtSubject.Rows)
{
XElement subject = new XElement("subject");
subject.SetAttributeValue("id", row["num"]);
subject.SetAttributeValue("name", row["name"]);
subject.SetAttributeValue("short", row["name"].ToString().Substring(0, 2));
subjects.Add(subject);
}
}
if (classes != null)
{
foreach (DataRow row in dtClassRoom.Rows)
{
XElement cls = new XElement("classroom");
cls.SetAttributeValue("id", row["id"]);
cls.SetAttributeValue("name", row["name"]);
cls.SetAttributeValue("short", row["name"].ToString().Substring(0, 2));
classes.Add(cls);
}
}
XElement xml = new XElement("timetable",
new XAttribute("importtype", "database"),
new XAttribute("options", "idprefix:id"),teachers,subjects,classes
);
doc.Add(xml);
string dirPath = System.Web.HttpContext.Current.Server.MapPath("~/import");
string targetFileName = Path.Combine(dirPath, "import.xml");
int counter = 1;
while (System.IO.File.Exists(targetFileName))
{
counter++;
targetFileName = Path.Combine(dirPath,
"import" + counter.ToString() + ".xml");
}
doc.Save(targetFileName);
}
You may try to read and update XML document using Linq-XML.
Have a look at sample:
//Read the teachers element from xml schema file
XElement teachers = XDocument.Load(schemaFile).Descendants("teachers").SingleOrDefault();
if (teachers != null)
{
DataTable dt = new DataTable();
dt.Columns.Add("id");
dt.Columns.Add("name");
dt.Rows.Add("1", "john");
dt.Rows.Add("2", "philips");
dt.Rows.Add("3", "sara");
XDocument doc = new XDocument();
foreach (DataRow row in dt.Rows)
{
XElement teacher = new XElement("teacher");
teacher.SetAttributeValue("id", row["id"]);
teacher.SetAttributeValue("name", row["name"]);
teacher.SetAttributeValue("short", row["name"].ToString().Substring(0,2));
teachers.Add(teacher);
}
doc.Add(teachers);
doc.Save(newFilename);
}

Categories