4

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!

waltmagic
  • 631
  • 2
  • 9
  • 22
  • 1
    The best way to figure out how xml serialization works, in my experience, is to create an instance of the type and serialize it, to see what the result looks like. You may see something crucial that you left out of the xml string in your test. – phoog Jun 05 '14 at 20:17
  • 1
    Ok I just tried to reproduce this and it seems there is a problem with the XmlSerialization code (error CS0030: Cannot convert type 'DeleteMe.WeeklyJobsDailyJobsJobsJob[]' to 'DeleteMe.WeeklyJobsDailyJobsJobsJob'/error CS0029: Cannot implicitly convert type 'DeleteMe.WeeklyJobsDailyJobsJobsJob' to 'DeleteMe.WeeklyJobsDailyJobsJobsJob[]'). I'm trying to figure it out. But I'll also say that my usual approach to this is to write my own classes by hand. I'll post another comment if I can find the problem. – phoog Jun 05 '14 at 22:13

1 Answers1

5

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.

Community
  • 1
  • 1
phoog
  • 42,068
  • 6
  • 79
  • 117
  • You are the Man! I would have to agree with your comment above. Instead of taking the xml web response that I was given and using the xsd.exe tool to create my schema and class I should have taken a step back and asked myself, what would this class look like? Then make alterations until my xml is appropriate to the web resonse. Thank you very much phoog, you have helped me gain some valuable knowledge. – waltmagic Jun 06 '14 at 14:14
  • now I am experiencing NullRefernceExceptions when I loop through my deserialized object. Its weird. I will have to post another [question](http://stackoverflow.com/questions/24086625/deserialized-xml-object-loop-throws-nullreferenceexception) to figure it out. – waltmagic Jun 06 '14 at 16:28