【问题标题】:write to xml file using linq使用 linq 写入 xml 文件
【发布时间】:2013-03-14 11:29:11
【问题描述】:

Writing to XML using XDocument, but knowing where to write类似于这个Qn。

希望你能帮我一点忙。我正在尝试更新 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.
}

【问题讨论】:

  • 只是为了确定 - 你是从 DataTable 到 xml 文件吗?

标签: c# xml linq


【解决方案1】:

使用此扩展方法,您可以将任何DataTable 转换为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)
                    )
                )
            );
    }
}

用法:

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

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

【讨论】:

    【解决方案2】:

    问题:

    您在 cmets 中声明您不确定如何添加将在生成的 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));
    

    【讨论】:

      【解决方案3】:

      如果您只是在寻找一种将 XElement 流式传输到文件的方法,那非常简单:

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

      【讨论】:

        猜你喜欢
        • 2015-05-19
        • 2019-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多