I have an xsd schema with an optional element (minOccurs=0
, maxOccurs=1
) of type int
. The element is NOT defined as nillable. In the d
I am not sure about XxxSpecified, but you can use the ShouldSerializeXxx methods. These happily work whether the property type is nullable or not. The following should do the job:
public int? Property { get ; set ; }
// this member is used for XML serialization
public bool ShouldSerializeProperty () { return Property.HasValue ; }
As for the generation of code from XSD schema, if you're using Microsoft's xsd.exe tool the best bet seems to be to post-process the generated assembly with e.g. Mono.Cecil to modify the types of the properties of interest and to insert any extra serialization-related members like ShouldSerializeXxx
. Adding an XSLT pre-processing step to run xsd.exe on a 'fixed' schema with nillable element declarations achieves the first goal, but not the second. xsd.exe is not flexible enough to do what you want. You might also try adding this functionality to xsd2code, since it's open-source.
I also encountered with this problem some time ago. I solved it by introducing additional property that handles serialization logic.
Firstly you mark your original property with [XmlIgnore] attribute to exlude it from serialization/deserialization.
// Mark your original property from serialization/deserialization logic
[XmlIgnore]
public int? OriginalProperty { get; set; }
Then add the additional property and mark it with [XmlElement("YourElementName")] attribute to handle serialization logic.
// Move serialization logic to additional string property
[XmlElement("OriginalPropertyXmlElement")]
public string OriginalPropertyAsString
{
get
{
//...
}
set
{
//...
}
}
On deserialization it will:
set
{
// Check the field existence in xml
if (string.IsNullOrEmpty(value))
{
// Set the original property to null
this.OriginalProperty = default(int?);
}
else
{
// Get value from xml field
this.OriginalProperty = int.Parse(value);
}
}
On serialization:
get
{
if (this.OriginalProperty.HasValue)
{
// Serialize it
return this.OriginalProperty.ToString();
}
else
{
// Don't serialize it
return null;
}
}
The example could look like:
[XmlRoot("scene")]
public class Scene
{
[XmlIgnore]
public int? ParentId { get; set; }
[XmlElement("parent_id")]
public string ParentIdAsString
{
get
{
return this.ParentId.HasValue ? this.ParentId.ToString() : null;
}
set
{
this.ParentId = !string.IsNullOrEmpty(value) ? int.Parse(value) : default(int?);
}
}
}
It's pretty simple and you don't have to write your own serializer nor hacking xsd nor other stuff.