【问题标题】:DataTable to Xdocument CustomDataTable 到 Xdocument 自定义
【发布时间】:2013-07-25 20:57:42
【问题描述】:

我有一个如下所示的数据表

type                cname   ctable      text          allowgroupping
StringFilter         AAA     Table1      Good,Bad      Yes
StringFilter         BBB     Table2      Ugly          No
StringFilter         CCC     Table3      Lucky         Yes

我想从该表中生成以下 XML

<Filters Date ="25.07.2012 22:50">
<StringFilter cname="AAA" ctable="Table1" allowgroupping="Yes">Good,Bad</StringFilter>
<StringFilter cname="BBB" ctable="Table2" allowgroupping="No">Ugly</StringFilter >
<StringFilter cname="CCC" ctable="Table3" allowgroupping="Yes">Lucky</StringFilter >
</Filters>
  • 类型列代表标签
  • cname 和 ctable 和 allowgroupping 是属性
  • 列文本表示内部文本

您能帮我使用 linq 和 xDocument 实现这一目标吗?

【问题讨论】:

    标签: c# linq linq-to-xml


    【解决方案1】:

    添加对System.Data.DataSetExtensions的引用

    using System.Data.DataSetExtensions;
    
    var XDocument doc = new XDocument();
    var root =  new XElement("Filters");
    
    var items = dt.Rows.AsIEnumberable().Select(row=> new XElement("StringFilter",             new XAttribute("cname",(string) row["cname"]),
        /*additional attributes here*/
         (string) row["text"]  ));
    
    root.Add(items);
    doc.Add(root);
    

    【讨论】:

      【解决方案2】:

      @CamBruce 给出了正确答案。
      System.Data.DataSetExtensions 是不必要的
      如果您使用AsEnumerable 而不是AsIEnumberable
      下面是一个使用子元素的工作示例:

      //Build DataTable for the purposes of this Example:
      DataTable dt = new DataTable();
      //Add Columns:
      dt.Columns.Add("WidgetType");//The default Type is "string".
      dt.Columns.Add("WidgetID", typeof(int));
      dt.Columns.Add("WidgetName");
      dt.Columns.Add("WidgetPrice", typeof(decimal));
      dt.Columns.Add("SubWidget");
      //Add Rows:
      dt.Rows.Add("Watch",  1, "Dial",     .50, "Gear");
      dt.Rows.Add("Tablet", 2, "Screen", 14.99, null);
      dt.Rows.Add("Watch",  3, "Strap",   1,    "Buckle");
      
      //Prep XML Objects:
      XDocument xDoc = new XDocument();
      //xDoc.Declaration = new XDeclaration("1.0", "utf-16", null);//Optional: SQL-Server already stores XML using UTF-16.  The default for XDocument is also UTF-16 when the Declaration is null. - 07/26/2018 - MCR.
      XElement xRoot = new XElement("Root");
      xRoot.SetAttributeValue("Date", string.Format("{0:MM/dd/yyyy hh:mm tt}", DateTime.Now));//Optional: Add Attribute to Root.
      
      //Populate XML from DataTable:
      xRoot.Add(dt.AsEnumerable()
                  //.Where(r => r.Field<string>("WidgetType") == "Watch")//Optional: Add Filter.  This works.
                  .Select(r => new XElement(r.Field<string>("WidgetType"),//Add Row Element
                                            //r.Field<decimal>("WidgetPrice"),//Optional: Populate Element Value.
                                            new XAttribute("WidgetID",   r.Field<int>("WidgetID")),//Optional: Add Attribute.
                                            new XAttribute("WidgetName", r.Field<string>("WidgetName")),//Optional: Add Attribute.
                                            new XElement("SubWidget", r.Field<string>("SubWidget"))//Optional: Add Child-Element.
                                           )
                         )
               );
      
      //Finish assembling the XML:
      xDoc.Add(xRoot);
      
      //View the XML Data:
      string sDoc = xDoc.ToString();//View Indented-XML as a string.
      
      //View the XML as it would appear in a Standalone File:
      System.IO.StringWriter sw = new System.IO.StringWriter();
      xDoc.Save(sw);
      string sWrite = sw.ToString();//This adds the XML Declaration to the string output.
      

      sDoc 字符串:

      <Root Date="07/26/2018 04:07 AM">
        <Watch WidgetID="1" WidgetName="Dial">
          <SubWidget>Gear</SubWidget>
        </Watch>
        <Tablet WidgetID="2" WidgetName="Screen">
          <SubWidget />
        </Tablet>
        <Watch WidgetID="3" WidgetName="Strap">
          <SubWidget>Buckle</SubWidget>
        </Watch>
      </Root>
      

      sWrite 字符串:

      <?xml version="1.0" encoding="utf-16"?>
      <Root Date="07/26/2018 04:07 AM">
        <Watch WidgetID="1" WidgetName="Dial">
          <SubWidget>Gear</SubWidget>
        </Watch>
        <Tablet WidgetID="2" WidgetName="Screen">
          <SubWidget />
        </Tablet>
        <Watch WidgetID="3" WidgetName="Strap">
          <SubWidget>Buckle</SubWidget>
        </Watch>
      </Root>
      

      使用它来将 XDocument 作为 Xml 参数值传递给 SQL Server Sproc:

      cmd.Parameters.Add("@WidgetXml", SqlDbType.Xml).Value
       = new System.Data.SqlTypes.SqlXml(xDoc.CreateReader());
      

      如果写入文件,我会使用xDoc.Save(FileName)
      如果您想准确预览 XML 在文件中的显示方式,请使用 StringWriter
      如果您希望在调试/故障排除时获得数据元素的基本/简单视图,
      那么您可以在单步执行代码时使用 xDoc.ToString(),但请注意,它可能会遗漏一些内容,例如声明。

      我不是 XML 专家,但我认为 StringWriterxDoc.Save(FileName) 应该将附加/必要信息添加到您的 XML 输出中(甚至超出 XML 声明 - 取决于您在 XML 变量中设置的属性)。
      也许有人可以权衡他们过去在 cmets 的经历。

      【讨论】:

        猜你喜欢
        • 2021-11-04
        • 2021-11-20
        • 1970-01-01
        • 2020-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-03
        • 2010-11-20
        相关资源
        最近更新 更多