I'm trying to manually deserialize a hierarchy of data objects (full code down below), but getting an exception I do not understand.
DEMDataSet
contains a collection ofDemographicReportGroup
objects.DemographicReportGroup
implementsIXmlSerializable
, containsAgency
object.Agency
object contains the leaf data itemdAgency.01
, akaEMSAgencyUniqueStateID
.
I'm working on implementing the ReadXml
method for DemographicReportGroup
, but I get an exception thrown as follows:
#region ReadXml
public void ReadXml(System.Xml.XmlReader xmlReader)
{
xmlReader.MoveToContent();
this.timeStamp = DateTime.Parse(xmlReader.GetAttribute("timeStamp"));
if (xmlReader.IsEmptyElement) return;
xmlReader.ReadStartElement();
if (xmlReader.Name == "dAgency")
{
xmlReader.ReadStartElement("dAgency");
// **Exception here: System.InvalidOperationException**
this.Agency = new XmlSerializer(typeof(Agency)).Deserialize(xmlReader) as Agency;
xmlReader.ReadEndElement();
}
xmlReader.ReadEndElement();
}
#endregion
System.InvalidOperationException: <dAgency.01 xmlns='http://www.nemsis.org'> was not expected.
All the code samples I've found so far indicate that this should work... Perhaps it's a misconfiguration of the XML attributes?
Hopefully someone can help!
Also, in case you are curious:
- Why are you implementing
IXmlSerializable
at all?- The
timeStamp
property is a date/time. If it was a plainDateTime
, it would always have a value (1/1/0001) when it is serialized. TheDateTime?
type lets me know when it does not have a value, but it cannot be serialized as an attribute. The data standard that this example is a part of dictates that the time stamp must be an attribute.
- The
- What about implementing a ShouldSerializetimeStampValue?
- That would make an extra property and extra method (timeStampValue and ShouldSerializetimeStampValue), which is too much code for one data item. Also, this is not the only time stamp I'm dealing with.
Full code (as unit test for Visual Studio):
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization; // System.Xml.dll.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Tests.Xml
{
[TestClass]
public class TestIXmlSerializable
{
[TestMethod]
public void DeserializeChildElement()
{
var xml = @"<DEMDataSet xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:schemaLocation=""http://www.nemsis.org http://nemsis.org/media/XSD_v3/_nemsis_v3.3.1/3.3.1.130201/XSDs/NEMSIS_XSDs_v3.3.1.130201/DEMDataSet_v3.xsd"" xmlns=""http://www.nemsis.org"">
<DemographicReport timeStamp=""1969-03-14T07:38:20+07:00"">
<dAgency>
<dAgency.01>M</dAgency.01>
</dAgency>
</DemographicReport>
</DEMDataSet>";
var xmlSerializer = new XmlSerializer(typeof(DEMDataSet));
DEMDataSet demDataSet = null;
using (var streamReader = new StringReader(xml))
demDataSet = xmlSerializer.Deserialize(streamReader) as DEMDataSet;
}
}
[Serializable]
/// <summary>Root Tag For Demographic DataSet</summary>
[XmlType(AnonymousType = true, Namespace = "http://www.nemsis.org")]
[XmlRoot(Namespace = "http://www.nemsis.org", IsNullable = false)]
public partial class DEMDataSet
{
#region DemographicReportGroup
private List<DemographicReportGroup> _demographicReportGroup;
/// <summary>Container Tag to hold each instance of a demographic record</summary>
[XmlElement("DemographicReport")]
public List<DemographicReportGroup> DemographicReportGroup
{
get
{
return this._demographicReportGroup;
}
set
{
this._demographicReportGroup = value;
}
}
#endregion
}
[Serializable]
public partial class DemographicReportGroup : IXmlSerializable
{
#region Agency
private Agency _agency;
/// <summary></summary>
[XmlElement("dAgency", IsNullable = false)]
public Agency Agency
{
get
{
return this._agency;
}
set
{
this._agency = value;
}
}
#endregion
#region timeStamp
private DateTime? _timeStamp;
/// <summary></summary>
[XmlAttribute]
public DateTime? timeStamp
{
get
{
return this._timeStamp;
}
set
{
this._timeStamp = value;
}
}
#endregion
#region GetSchema
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
#endregion
#region ReadXml
public void ReadXml(System.Xml.XmlReader xmlReader)
{
xmlReader.MoveToContent();
this.timeStamp = DateTime.Parse(xmlReader.GetAttribute("timeStamp"));
if (xmlReader.IsEmptyElement) return;
xmlReader.ReadStartElement();
if (xmlReader.Name == "dAgency") { xmlReader.ReadStartElement("dAgency"); this.Agency = new XmlSerializer(typeof(Agency)).Deserialize(xmlReader) as Agency; xmlReader.ReadEndElement(); }
xmlReader.ReadEndElement();
}
#endregion
#region WriteXml
public void WriteXml(System.Xml.XmlWriter xmlWriter)
{
if (this.timeStamp.HasValue) xmlWriter.WriteAttributeString("timeStamp", this.timeStamp.Value.ToString("o"));
if (this.Agency != null) { xmlWriter.WriteStartElement("dAgency"); new XmlSerializer(typeof(Agency)); xmlWriter.WriteEndElement(); }
}
#endregion
}
[Serializable]
/// <summary></summary>
[XmlType(Namespace = "http://www.nemsis.org")]
[XmlRoot(Namespace = "http://www.nemsis.org", IsNullable = true)]
public partial class Agency
{
#region EMSAgencyUniqueStateID
private string _emsAgencyUniqueStateID;
/// <summary>The unique ID assigned to the EMS Agency which is associated with all state licensure numbers and information.</summary>
[XmlElement("dAgency.01")]
public string EMSAgencyUniqueStateID
{
get
{
return this._emsAgencyUniqueStateID;
}
set
{
this._emsAgencyUniqueStateID = value;
}
}
#endregion
}
}