2013-03-14 150 views
4

Writing to XML using XDocument, but knowing where to write類似於這個Qn。用linq寫入xml文件

希望你能幫助我一下。我正在嘗試更新XML文件,但我正在努力編寫寫入XML文件的方法。 這是XML文件

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

這裏的用戶可以更改/添加標籤,即,名或路徑下software_entry是未知的,因爲用戶可以編輯/添加值。除格式外,一切都是未知的。

我能夠讀取該文件,其存儲在一個DataTable,填充到電網,等等。使用LINQ

然而,編輯表格而寫爲xml我堅持以後。

任何人都可以請幫我寫這種數據到XML?

到目前爲止我嘗試這樣做:

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. i.e, 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. 
} 
+0

只是可以肯定 - 你從'DataTable'to XML文件中去? – 2013-03-14 12:18:54

回答

2

問題:

您在您的評論中聲明,您不確定如何添加將在您的結果XML中創建屬性的內部元素。你的代碼的其餘部分完美的作品,除了這一點:

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

解決方案

你想要的缺失部分是遍歷這些都對DataTable列,然後訪問每行的列的值。這是因爲DataRow對象沒有關於列名的信息。

因此,您需要通過DataTable.Columns集合的另一個內部循環,然後使用DataRow列訪問器dt.Rows[j][column]從當前列中獲取值。

它看起來像這樣:

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

我與你的代碼測試:

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. i.e, 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(); 
     } 
    } 
} 

獎金 - 因爲我要試試這個

這裏有一個辦法做到這一點完全使用LINQ :(使用與我之前的例子相同的測試數據)

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

如果你只是在尋找一種方式來流您XElements到一個文件中,這是相當容易:

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

有了你可以將任何DataTableXElement此擴展方法:

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

用法:

DataTable table = new DataTable("software"); 
table.Columns.Add("name"); 
table.Columns.Add("path"); 
// add rows to table 

XElement software = table.ToXml("software_element");