简体   繁体   中英

Deserialize Xml Using XmlReader and Class from xsd.exe

OK I have hit a snag trying to learn XmlSerializer while going through some tutorials. I have followed all the recommended steps but my program is not returning anything, or is returning null. I created an XML file as follows:

<?xml version='1.0' encoding='UTF-8' ?>
<WeeklyJobs>
   <DailyJobs Date = "02/03/2012"/>
  <DailyJobs Date = "02/04/2012" TotalJobs = "2">
    <Jobs>
      <Job JobName = "Job Name" Description = "Description"/>
      <Job JobName = "Job Name" Description = "Description"/>
    </Jobs>
  </DailyJobs>
  <DailyJobs Date = "02/05/2012" TotalJobs = "1">
    <Jobs>
      <Job JobName = "Job Name" Description = "Description"/>
    </Jobs>
  </DailyJobs>
  <DailyJobs Date = "02/06/2012" TotalJobs = "2">
    <Jobs>
      <Job JobName = "Job Name" Description = "Description"/>
      <Job JobName = "Job Name" Description = "Description"/>
    </Jobs>
  </DailyJobs>
  <DailyJobs Date = "02/07/2012"/>
  <DailyJobs Date = "02/08/2012" TotalJobs = "2">
    <Jobs>
      <Job JobName = "Job Name" Description = "Description"/>
      <Job JobName = "Job Name" Description = "Description"/>
    </Jobs>
  </DailyJobs>
</WeeklyJobs>

I then used xsd.exe to generate the .xsd file which is:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="WeeklyJobs" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema"     xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="WeeklyJobs" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="DailyJobs">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Jobs" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Job" minOccurs="0" maxOccurs="unbounded">
                      <xs:complexType>
                        <xs:attribute name="JobName" type="xs:string" />
                        <xs:attribute name="Description" type="xs:string" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="Date" type="xs:string" />
            <xs:attribute name="TotalJobs" type="xs:string" />
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

After creating the schema I used xsd.exe again to auto generate the class for me which is:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class WeeklyJobs
{

    private WeeklyJobsDailyJobs[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("DailyJobs", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public WeeklyJobsDailyJobs[] Items
    {
        get
        {
            return this.itemsField;
        }
        set
        {
            this.itemsField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class WeeklyJobsDailyJobs
{

    private WeeklyJobsDailyJobsJobsJob[][] jobsField;

    private string dateField;

    private string totalJobsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlArrayItemAttribute("Job", typeof(WeeklyJobsDailyJobsJobsJob), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable = false)]
    public WeeklyJobsDailyJobsJobsJob[][] Jobs
    {
        get
        {
            return this.jobsField;
        }
        set
        {
            this.jobsField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string Date
    {
        get
        {
            return this.dateField;
        }
        set
        {
            this.dateField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string TotalJobs
    {
        get
        {
            return this.totalJobsField;
        }
        set
        {
            this.totalJobsField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class WeeklyJobsDailyJobsJobsJob
{

    private string jobNameField;

    private string descriptionField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string JobName
    {
        get
        {
            return this.jobNameField;
        }
        set
        {
            this.jobNameField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string Description
    {
        get
        {
            return this.descriptionField;
        }
        set
        {
            this.descriptionField = value;
        }
    }
}

After this I added the .CS file to my project and created a simple winform with a TextBox to display some data once I have deserialized some xml. Like I said the program launches and nothing is displayed in the TextBox and no Exceptions are thrown. Here is my winform:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

    }

    public string getExample()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(WeeklyJobs));
        WeeklyJobs jobs;
        string xml = @"<?xml version = ""1.0""?>"
            + @"<WeeklyJobs>"
            + @"<DailyJobs Date = ""02/03/2012""/>"
            + @"<DailyJobs Date = ""02/04/2012"" TotalJobs = ""2"">"
            + @"<Jobs>"
            + @"<Job JobName = ""Job Name"" Description = ""Description""/>"
            + @"<Job JobName = ""Job Name"" Description = ""Description""/>"
            + @"</Jobs>"
            + @"</DailyJobs>"
            + @"</WeeklyJobs>";

        // Create an XmlTextReader
        using (XmlReader reader = XmlReader.Create(new StringReader(xml)))
        {
            jobs = (WeeklyJobs)serializer.Deserialize(reader);
        }

        return jobs.Items[0].Date;

    }

    private void Form1_Load(object sender, EventArgs e)
    {
        textBox1.Text = getExample();

    }


}

I have got much more simple xml examples to work but I the second I try to add some complexity to my xml I fail. I have to figure out how to use the xml I have here. I appreciate the help! Thanks everyone!

Ok, the first problem is that the XmlSerializer constructor is raising an unhandled exception, but that is somehow getting swallowed. This explains why the text box is empty. I set the debugger to break on all CLR exceptions, and found that the constructor was throwing an InvalidOperationException -- apparently during the code generation process:

Unable to generate a temporary class (result=1).

error CS0030: Cannot convert type 'DeleteMe.WeeklyJobsDailyJobsJobsJob[]' to 'DeleteMe.WeeklyJobsDailyJobsJobsJob'

error CS0029: Cannot implicitly convert type 'DeleteMe.WeeklyJobsDailyJobsJobsJob' to 'DeleteMe.WeeklyJobsDailyJobsJobsJob[]'

(The constructor was also throwing a FileNotFound exception, but it also handles that, so you can ignore it.)

It seems the problem is the jagged arrays -- did you change 1-dimensional arrays to jagged arrays? The error message pointed me in that direction, of course, but I have also never seen jagged arrays in xsd-generated code, so it looked suspicious. I changed two occurrences of WeeklyJobsDailyJobsJobsJob[][] to WeeklyJobsDailyJobsJobsJob[] and the application worked just fine.

As an aside, you should use DateTime for your dates, but XML serializer does not support variable date formats (see https://stackoverflow.com/a/1118855/385844 ). If you have no control over the source, you're probably better off converting the strings to dates before you store them in your database or wherever.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM