Write to xml file using linq

Writing to XML using XDocument, but knowing where to write is similar to Qn.

Hope you can help me a bit. I am trying to update an XML file, but I am struggling to write a method that writes to an XML file. This is an XML file

<software> <software_entry name="Adobe Acrobat X Standard" path="Applications\Acrobat\Acrobat XStandard\AcroStan.msi" /> .. </software> <ApplicationConfigurations> <Config name ="someName" value ="someValue"/> .. </ApplicationConfigurations> 

Here the user can change / add tags, i.e. the name or path under software_entry is unknown, as the user can edit / add values. In addition to the format, everything is unknown.

I can read the file, save it in a DataTable , fill it with a grid, etc. using LINQ

However, after editing the table while writing to xml, I got stuck.

Can someone help me write this kind of data in xml?

I have tried this so far:

 for (int i = 0; i < dt.Length; i++) //for every table { XName TableName = dt[i].TableName; //table name. XElement[] xInnerElt = new XElement[dt[i].Rows.Count]; //for n rows inside one table for (int j = 0; j < dt[i].Rows.Count; j++) //loop each tag inside the table { XName InnerTagName = htAtributNameForTable[dt[i].TableName].ToString(); //tag name form hash table. ie, software_entry //I am unable to write the next line xInnerElt[j] = new XElement(InnerTagName,new XAttribute((XName)ColumnName,rows Item arry)), //loop till all column added } XElement xElt = new XElement(TableName, xInnerElt); //one table aded to tag. } 
+4
source share
3 answers

Problem:

In your comments, indicate that you do not know how to add internal elements that will create attributes in the resulting XML. The rest of your code works fine except for this bit:

  //I am unable to write the next line xInnerElt[j] = new XElement(InnerTagName,new XAttribute((XName)ColumnName,rows Item arry)), 

Decision

The unacceptable part you want is to skip the columns located on the DataTable , and then access the column values ​​in the row. This is because the DataRow object does not have column name information.

Therefore, to get the value from the current column, you need another inner loop through the DataTable.Columns collection, and then use the dt.Rows[j][column] element for the DataRow column dt.Rows[j][column] .

It looks like this:

  foreach (var column in dt[i].Columns) { xInnerElt[j].Add( new XAttribute( (column as DataColumn).ColumnName, dt[i].Rows[j][(column as DataColumn)].ToString() ) ); } 

My test with code:

 using System; using System.Collections.Generic; using System.Data; using System.Xml.Linq; namespace XElemFromDT { class Program { static void Main(string[] args) { Dictionary<string, string> htAtributNameForTable = new Dictionary<string, string>() { { "Software", "software_entry" }, { "ApplicationConfigurations", "config" } }; DataTable dt1 = new DataTable(); dt1.TableName = "Software"; dt1.Columns.Add("name", typeof(string)); dt1.Columns.Add("path", typeof(string)); dt1.Rows.Add("Adobe Acrobat X Standard", @"Applications\Acrobat\Acrobat XStandard\AcroStan.msi"); dt1.Rows.Add("Adobe Photoshop", @"Applications\Photoshop\Photoshop.msi"); DataTable dt2 = new DataTable(); dt2.TableName = "ApplicationConfigurations"; dt2.Columns.Add("name", typeof(string)); dt2.Columns.Add("value", typeof(string)); dt2.Rows.Add("someName", "someValue"); dt2.Rows.Add("someOtherName", "someOtherValue"); DataTable[] dt = new DataTable[] { dt1, dt2 }; XDocument xDoc = new XDocument(new XElement("Root")); for (int i = 0; i < dt.Length; i++) //for every table { XName TableName = dt[i].TableName; //table name. XElement[] xInnerElt = new XElement[dt[i].Rows.Count]; //for n rows inside one table for (int j = 0; j < dt[i].Rows.Count; j++) //loop each tag inside the table { XName InnerTagName = htAtributNameForTable[dt[i].TableName].ToString(); //tag name form hash table. ie, software_entry //I am unable to write the next line xInnerElt[j] = new XElement(InnerTagName); foreach (var column in dt[i].Columns) { xInnerElt[j].Add( new XAttribute( (column as DataColumn).ColumnName, dt[i].Rows[j][(column as DataColumn)].ToString() ) ); } } XElement xElt = new XElement(TableName, xInnerElt); //one table aded to tag. xDoc.Root.Add(xElt); } Console.WriteLine(xDoc.ToString()); Console.ReadKey(); } } } 

Bonus - because I had to try this

Here you can do it completely with LINQ: (using the same test data as my previous example)

  DataTable[] dt = new DataTable[] { dt1, dt2 }; XDocument xDoc = new XDocument(new XElement("Root")); Func<DataTable, DataRow, IEnumerable<XAttribute>> getAttributes = (t, r) => t.Columns.OfType<DataColumn>().Select(c => new XAttribute(c.ColumnName, r[c].ToString())); Func<DataTable, IEnumerable<XElement>> getElements = t => t.Rows.OfType<DataRow>().Select(r => new XElement(htAtributNameForTable[t.TableName], getAttributes(t, r))); Func<DataTable[], IEnumerable<XElement>> getTables = dtc => dtc.AsEnumerable().Select(t => new XElement(t.TableName, getElements(t))); xDoc.Root.Add(getTables(dt)); 
+2
source

Using this extension method, you can convert any DataTable to an XElement :

 public static class Extensions { public static XElement ToXml(this DataTable table, string rowElementName) { // check if table has name and rowElementName is not empty return new XElement( new XElement(table.TableName, from row in table.AsEnumerable() select new XElement(rowElementName, from column in table.Columns.Cast<DataColumn>() let value = row.Field<string>(column) where value != null select new XAttribute(column.Caption, value) ) ) ); } } 

Using:

 DataTable table = new DataTable("software"); table.Columns.Add("name"); table.Columns.Add("path"); // add rows to table XElement software = table.ToXml("software_element"); 
+3
source

If you're just looking for a way to stream XElements to a file, this is pretty easy:

  using (XmlWriter writer = XmlWriter.Create("filename.xml")) { writer.WriteStartElement("DocumentElementName"); // Your code goes here xElt.WriteTo(writer); writer.WriteEndElement(); } 
+1
source

Source: https://habr.com/ru/post/1469208/


All Articles