DataTable.WriteXML()没有详细的Namespace和DataType声明

时间:2014-06-16 20:20:03

标签: c# .net xml

我将一个简单的DataTable序列化为XML,并将结果存储在一个字符串中。使用StringWriter和DataTable.WriteToXml,这很好。

public class Parameters
{   private DataTable ParamList = new DataTable();

    public Parameters()
    {   //Default constructor, build datatable with two empty columns
        ParamList.TableName = "Parameter";
        ParamList.Columns.Add("Name",Type.GetType("System.String"));
        ParamList.Columns.Add("Value",Type.GetType("System.Object")); }
    ...
    public string ConvertToXML()
    {   string result;
        using(var sw = new System.IO.StringWriter())
        {   ParamList.WriteXml(sw);
            result = sw.ToString();
        }
        return result;
    }
}

这与宣传的一样。但是,在定义字段时,XML非常冗长:

<DocumentElement>
  <Parameter>
    <Name>ClientNumber</Name>
    <Value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">00001</Value>
  </Parameter>
  <Parameter>
    <Name>FirstName</Name>
    <Value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">John</Value>
  </Parameter>
  <Parameter>
    <Name>LastName</Name>
    <Value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Smith</Value>
  </Parameter>
...

我想在VALUE字段中删除所有命名空间和数据类型声明,就像显示NAME字段一样。我已经玩弄了XmlWriterSettings(),但似乎无法找到任何设置来实现这一目标。有什么想法吗?我建议可能吗?

(注1:我的目的只是将数据表中的字段和值记录到SQL表中,由于字段和值的数量可能不同,这似乎是最简单的方法.XML赢了读回来,所以强类型数据元素对我的目标并不重要。)

(注2:我希望在不使用RegEx的情况下实现这一目标,但如果这是我唯一的选择,那可能就是我的方向。)

  

可能重复? :Serialize into an XML Fragment - not XML Document

查看此内容,但无法调整语法以使用DataTable。

4 个答案:

答案 0 :(得分:1)

这是我尝试过的完整程序 - 所以Holder用于保存任何内容并序列化值:

 public class Holder:IXmlSerializable
{
    public object Data { get; set; }
    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
    }

    public void WriteXml(XmlWriter writer)
    {
       writer.WriteString(Data.ToString());
    }
}
public class DataTableManager
{
    public static void Save()
    {
        DataTable dataTable = new DataTable("table1");
        DataColumn dataColumn = new DataColumn("Column1",typeof(string));
        DataColumn dataColumn2 = new DataColumn("Column2",typeof(Holder));
        dataTable.Columns.Add(dataColumn);
        dataTable.Columns.Add(dataColumn2);
        dataTable.Rows.Add("ro2", new Holder(){Data = 1});
        dataTable.Rows.Add("ro3", new Holder() { Data = "Test" });
        dataTable.Rows.Add("ro4", new Holder() { Data = new decimal(10) });

        Debug.WriteLine(dataTable.Namespace);
        //To file:
        dataTable.WriteXml(@"c:\development\datatable.xml",XmlWriteMode.IgnoreSchema);
        //To string
        StringBuilder stringBuilder = new StringBuilder();
        dataTable.WriteXml(new StringWriter(stringBuilder));
        Debug.WriteLine(stringBuilder.ToString());
    }
}

这将生成没有任何名称空间的xml,并将创建如上所述的三行。 enter image description here

答案 1 :(得分:1)

我提出了一个解决方案,但在我宣布这个答案之前,我等待更多有经验的意见。

正如我在评论中指出的那样,Namespace和Datatype声明只出现在Value字段中,因为它在DataTable声明中被强制转换为Object。这具有功能价值,所以我无法改变它。但我可以克隆表,在克隆的数据表仍然为空时更改字段的数据类型,用原始数据表中的数据填充表,然后执行我原来的相同WriteXML()。

Public class Parameters
{   private DataTable ParamList = new DataTable();

    public Parameters()
    {   //Default constructor, build datatable with two empty columns
        ParamList.TableName = "Parameter";
        ParamList.Columns.Add("Name",typeof(string));
        ParamList.Columns.Add("Value",typeof(object)); }
    ...
    public string ConvertToXML()
    {   string result;

        //Clone Datatable, change Object field to datatype String
        var dtClone = ParamList.Clone();
        dtClone.Columns["Value"].DataType = typeof(string);
        ParamList.AsEnumerable().CopyToDataTable(dtClone, LoadOption.OverwriteChanges);

        using(var sw = new System.IO.StringWriter())
        {   dtClone.WriteXml(sw);
            result = sw.ToString();
        }
        return result;
    }
}

输出:

<DocumentElement>
  <Parameter>
    <Name>ClientNumber</Name>
    <Value>00001</Value>
  </Parameter>
  <Parameter>
    <Name>FirstName</Name>
    <Value>John</Value>
  </Parameter>
  <Parameter>
    <Name>LastName</Name>
    <Value>Smith</Value>
  </Parameter>
...

答案 2 :(得分:0)

你上面所做的实际上是Avneesh建议的(编辑前)。

如果你真的想忍受,那么继承XmlWriter。这是抽象类。要在序列化中使用它,请执行以下操作:

DataTable dt;

var myXmlSerialization = new MyXmlWriter();

dt.WriteXml(myXmlSerialization);

可以找到XmlWriter实现的示例here

我建议你不要。

答案 3 :(得分:0)

这很简单。如果你有SomeDataSet,只需将它的前缀和名称空间设置为null:

SomeDataSet.Prefix = null;
SomeDataSet.Namespace = null;
SomeDataSet.Table.WriteXml(filename);