打开空数据表时XmlTextReader中是否有错误?

时间:2009-03-27 09:59:02

标签: c# xml-serialization

在保存不包含任何数据的DataTable时,我在c#中使用XmlSerializer和XmlTextReader时遇到了一些问题。这是一个已知问题,是否有解决方法?使用XMLSerializer保存空数据表时,将生成以下XML:

      <Values>
        <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
          <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="Values" msdata:UseCurrentLocale="true">
            <xs:complexType>
              <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="Values">
                  <xs:complexType>
                  </xs:complexType>
                </xs:element>
              </xs:choice>
            </xs:complexType>
          </xs:element>
        </xs:schema>
        <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" />
      </Values>

当重新加载包含它的XML时,XMLTextReader会以静默方式失败,并且不会将空数据加载到XML之外的内容加载。此问题似乎是由xs:complexType中缺少xs:sequence / xs:元素条目引起的。这是一个错误,如果是的话,解决方法是什么?

以下c#程序演示了该问题。由于上述问题,它将输出dt3为空:

public class Data
{
    private DataTable dt1;
    private DataTable dt2;
    private DataTable dt3;

    public DataTable Dt1
    {
        get { return dt1; }
        set { dt1 = value; }
    }

    public DataTable Dt2
    {
        get { return dt2; }
        set { dt2 = value; }
    }

    public DataTable Dt3
    {
        get { return dt3; }
        set { dt3 = value; }
    }

    public void TestDataTables()
    {
        if(dt1 == null)
            Console.WriteLine("dt1 is null");
        if (dt2 == null)
            Console.WriteLine("dt2 is null");
        if (dt3 == null)
            Console.WriteLine("dt3 is null");
    }
}
class Program
{
    static void Main(string[] args)
    {
        // Create test object
        Data data = new Data();
        data.Dt1 = new DataTable("Test1");
        data.Dt1.Columns.Add("Foo");
        data.Dt2 = new DataTable("Test2");
        // Adding the following line make serialization work as expected
        //data.Dt2.Columns.Add("Foo");
        data.Dt3 = new DataTable("Test3");
        data.Dt3.Columns.Add("Foo");
        data.TestDataTables();

        // Save to XML
        TextWriter filewriter = new StreamWriter("foo.xml");
        XmlTextWriter writer = new XmlTextWriter(filewriter);
        writer.Formatting = Formatting.Indented;
        XmlSerializer s1 = new XmlSerializer(typeof(Data));
        s1.Serialize(writer, data);
        writer.Close();
        filewriter.Close();

        // Reload from XML
        TextReader filereader = new StreamReader("foo.xml");
        XmlTextReader reader = new XmlTextReader(filereader);
        XmlSerializer s2 = new XmlSerializer(typeof(Data));
        Data newData = s2.Deserialize(reader) as Data;
        newData.TestDataTables();

    }
}

3 个答案:

答案 0 :(得分:0)

我倾向于在数据集上使用write xml方法,你可以尝试将其作为解决方法。

http://msdn.microsoft.com/en-us/library/system.data.dataset.writexml.aspx

答案 1 :(得分:0)

(编辑后)

感谢您的示例代码。是的,我同意这是一个错误。对于变通方法......好吧,您可以默认添加一列吗?为避免交叉污染,您可以使用ShouldSerialize*

public bool ShouldSerializeDt1() {
    return dt1 != null && dt1.Columns.Count > 0;
}
public bool ShouldSerializeDt2() {
    return dt2 != null && dt2.Columns.Count > 0;
}
public bool ShouldSerializeDt3() {
    return dt3 != null && dt3.Columns.Count > 0;
}

至少然后是dt2被省略,而不是dt3。

答案 2 :(得分:0)

我刚刚在MSDN论坛上发布了此查询:

  

如何将空DataTable序列化为Session?   http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataset/thread/4704d53c-ca3a-4da1-8257-b2b05c2e9e32

在此处发布新主题之前,这是与您在此报道的问题相同吗? 我不确定因为我自己没有使用任何显式的Seialization,我只是将一个DataSet(包含一个没有行的DataTable)放入Session中,该会话在进程外保存/恢复。