I am trying to use XmlSerializer to serialize/deserialize SyncML. I am having difficulty with the pattern which occurs in the <Get>
tag as shown below:
<SyncML xmlns="SYNCML:SYNCML1.2">
<SyncHdr>
<VerDTD>1.2</VerDTD>
<VerProto>DM/1.2</VerProto>
<!-- etc. -->
</SyncHdr>
<SyncBody>
<Status>
<CmdID>100</CmdID>
<MsgRef>1</MsgRef>
<CmdRef>0</CmdRef>
<!-- etc. -->
</Status>
<Status>
<CmdID>103</CmdID>
<MsgRef>1</MsgRef>
<CmdRef>4</CmdRef>
<!-- etc. -->
</Status>
<Get>
<CmdID>104</CmdID>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
</Get>
<Get>
<CmdID>105</CmdID>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
</Get>
<Sequence>
<CmdID>107</CmdID>
<Replace>
<CmdID>108</CmdID>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
</Replace>
<Replace>
<CmdID>109</CmdID>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
</Replace>
<Get>
<CmdID>110</CmdID>
<Item>
<Target>
<!-- etc. -->
</Target>
</Item>
</Get>
</Sequence>
<Final/>
</SyncBody>
</SyncML>
My classes so far are as follows:
[XmlRoot("SyncML", Namespace = "SYNCML:SYNCML1.2")]
public class SyncML
{
[XmlElement]
public SyncHdr SyncHdr { get; set; }
[XmlArray("SyncBody")]
[XmlArrayItem("Status", Type = typeof(StatusCommand))]
[XmlArrayItem("Get", Type = typeof(GetCommand))]
public SyncBody SyncBody { get; set; }
}
public class SyncHdr
{
[XmlElement("VerDTD")]
public string VerDtd { get; set; }
[XmlElement("VerProto")]
public string VerProto { get; set; }
// etc.
}
public class SyncBody : List<SyncCommand>
{
}
public abstract class SyncCommand : List<Item>
{
[XmlElement("CmdID")]
public int CmdId { get; set; }
}
public class StatusCommand : SyncCommand
{
[XmlElement("MsgRef")]
public int MsgRef { get; set; }
[XmlElement("CmdRef")]
public int CmdRef { get; set; }
// etc.
}
public class GetCommand : SyncCommand
{
public List<Item> Items { get; set; }
}
public class Item
{
[XmlElement("Target")]
public Location Target { get; set; }
}
public class Location
{
[XmlElement("LocURI")]
public string LocUri { get; set; }
}
The problem is that in the XML, the Get
tag contains one property element (CmdID) (as does the Status
element, but also any number of Item elements. Is there a way to attribute up my GetCommand class to handle this? Do I need to compose my models differently?
You basic problem is that, in two places, you are inheriting from
List<T>
. This is not recommended (see here for a discussion) and in addition is not well supported by serializers, e.g. properties of lists are never serialized. Instead, use classes that contain lists, and mark those lists with[XmlElement]
to indicate they should be serialized without an outer wrapper element.Thus your model should look something like:
Demo fiddle #1 here.
Notes that I inserted
SyncCommandBase
as an abstract superclass ofSyncCommand
and madeFinalCommand
inherit from it because the<Final/>
element does not have a<CmdID>
child element.If you would prefer not to bind the
<Final/>
element into theSyncCommand
list, you can modify your model as follows to make it an explicit property in an intermediateSyncBody
class:Demo fiddle #2 here.