469,271 Members | 1,718 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,271 developers. It's quick & easy.

XmlSerializer Empty Element - NULL value

Hi,
I'm using XmlSerializer to create an object from the XML string. I
would like to know whether I can get a null value for an empty XML
element.
Actually the XmlSerializer assigns "" (empty string) for a string
if the corresponding element is missing in the XML.

Input XML:
<DemoClass><A>some value</A><B></B><DemoClass>

Class Structure:
public class DemoClass
{
public string A;
public string B;
}
It creates the object with the proper value for "A" and empty
string B.

Is there any way I can get null for "B" instead of "" (empty
string) ?

Thanks,
Kumar

Nov 2 '06 #1
7 31686
As this little program shows everything works fine in your code.
The only thing that is wrong is your input string for deserialization.

public class MainClass
{
public static void Main(string[] argv) {
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.Xml.Serialization.XmlSerializer ser = new
System.Xml.Serialization.XmlSerializer(typeof(Demo Class));

Console.WriteLine("Not null");
DemoClass demo = new DemoClass();
demo.B = "Not Null";
ser.Serialize(new System.IO.StringWriter(sb), demo);
Console.WriteLine(sb.ToString());
demo = ser.Deserialize(new System.IO.StringReader(sb.ToString()))
as DemoClass;
Console.WriteLine(demo.ToString());
Console.WriteLine();

Console.WriteLine("Null");
sb = new System.Text.StringBuilder();
demo = new DemoClass();
ser.Serialize(new System.IO.StringWriter(sb), demo);
Console.WriteLine(sb.ToString());
demo = ser.Deserialize(new System.IO.StringReader(sb.ToString()))
as DemoClass;
Console.WriteLine(demo.ToString());

Console.Read();
}

public class DemoClass
{
private string a = "Hello, World";
private string b;

public string A {
get { return a; }
set { a = value; }
}

public string B {
get { return b; }
set { b = value; }
}

public override string ToString()
{
return "A = " + a + Environment.NewLine + "B = " + b;
}
}

Nov 2 '06 #2
Actually the XmlSerializer assigns "" (empty string) for a string
if the corresponding element is missing in the XML.
"Missing" is very different to "empty"; your B is empty, not missing.

Anyway, no: it doesn't; first it initialises the class using the field
initialisers and the default ctor. Then it applies all the *found* items,
else applies the [DefaultValue] (if one) to any that were omitted. If it
isn't in the xml it isn't set, so it would remain null. I guess your *real*
class is initialising it to "", or the data is in the xml.

If you really want to turn an *included* (blank) <B></Bto a null, then:

If *all* "" values should become null you could simply use a property setter
of the form {...set {b = value == "" ? null : value;}}. Almost an inverse
coalesce...

If this only applies during desrialization, well, for binary serialization
you could hook some combination of [OnDeserializing], [OnDeserialized] and
IDeserializationCallback... but xml is trickier... you could possibly
implement IXmlSerializable, but this isn't trivial.

Marc
Nov 2 '06 #3
Hi Roman Wagner/ Marc Gravell,
Many thanks for your replies.

I should not have written "missing". Actually, It's an empty
element.

As you said, i can use setter method to control the value. However,
i've a problem in that.

If the element is missing, then XmlSerializer tries to set the
default values (0 for int, false for bool) to the properties. Actually,
i should get "null" value if the element is passed as empty.

If i pass the empty element, the CLR throws exception in case if the
elment corresponds to types like int or bool.

More over i wanted to have null values for all the elements which
are sent as empty elements. The class can have any type of properties
like int, bool or another type of class. Since i wanted to have null
for all the properties which are sent as empty elements, i used
nullable types for primitive types like int? (for int).

The problem happens when the XmlSerializer tries to create the
object. Since the empty element is not the correct value for int? type,
it throws error even before coming to the setter method only.

Marc, by saying i need to implement IXmlSerializable, do you mean i
mean i need to implement the interface for all the entities(classes) i
need to crate from XML? It would not be ideal as i've to create many
classes from XML.

Thanks,
Kumar
Marc Gravell wrote:
Actually the XmlSerializer assigns "" (empty string) for a string
if the corresponding element is missing in the XML.

"Missing" is very different to "empty"; your B is empty, not missing.

Anyway, no: it doesn't; first it initialises the class using the field
initialisers and the default ctor. Then it applies all the *found* items,
else applies the [DefaultValue] (if one) to any that were omitted. If it
isn't in the xml it isn't set, so it would remain null. I guess your *real*
class is initialising it to "", or the data is in the xml.

If you really want to turn an *included* (blank) <B></Bto a null, then:

If *all* "" values should become null you could simply use a property setter
of the form {...set {b = value == "" ? null : value;}}. Almost an inverse
coalesce...

If this only applies during desrialization, well, for binary serialization
you could hook some combination of [OnDeserializing], [OnDeserialized] and
IDeserializationCallback... but xml is trickier... you could possibly
implement IXmlSerializable, but this isn't trivial.

Marc
Nov 3 '06 #4
Well, at the end of the day what you are describing is not the standard xml
serialization in the XmlSerializer sense. So to compensate, I see various
routes:
1: write your own serializer (hard work)
2: forget serializers and just do manual xml parsing yourself (also work)
3: have your objects implement IXmlSeriazable (hard work lots of times)
4: run the transmitted xml through e.g. xslt to convert between the form
that XmlSerializer likes and the form that you like... not sure how this
would compensate for missing xml fields that you need to generate an xsi:nul
entry for...
5: press to change the xml format? (not always achievable)

....

unfortunately, XmlSerializer is not as free-form as binary serialization,
which allows a few more tricks more easily (such as the before/after
"events" (attributed methods).

Marc
Nov 3 '06 #5
And an afterthought...

in most common usage, <element></elementwould be read "element is defined
as having a blank (i.e. empty string) value", which is what XmlSerializer is
doing. The omission of an element commonly means "leave it alone" / "default
value", with nullable types being handled a bit more subtly...

Just an observation...

Marc
Nov 3 '06 #6
Hi Marc,
The reason for this kind of requirement is that the same XML is used
for both insert and update actions. During the update I may get only
the updated elements. More over if the element is set to null, i'll get
an empty element. I need this empty element to distinguish from the
other non updated elements.

Many thanks for all your replies.

Regards,
Kumar
Marc Gravell wrote:
And an afterthought...

in most common usage, <element></elementwould be read "element is defined
as having a blank (i.e. empty string) value", which is what XmlSerializer is
doing. The omission of an element commonly means "leave it alone" / "default
value", with nullable types being handled a bit more subtly...

Just an observation...

Marc
Nov 6 '06 #7
Then presumably you are either doing the "WriteXml" step yourself
already, or consuming an existing feed that you aren't editing. In this
scenario, I might start looking at a simple, re-usable custom xml
parser using the component model... something as simple as:

* read (object) xml element
* identify object name [some custom mapping]
* read (property) xml element
* identify property name
* obtain object project via reflection / component-model
* set value
* loop property
* loop object

This would give you full control to interpret blank / missing as
whatever you want, yet without requiring custom code at an
object-by-object basis. Fundamentally this is very similar to the
approach taken by XmlSerializer. The other advantage is that it allows
you to decide very early on whether you are constructing a new object,
or applying the xml [effectively a diffgram] to an existing object;
XmlSerializer can only create.

On a purist note, I also like to distinguish between the empty string
and a null, but if this treatment works for your purposes...

Marc

Nov 6 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Tom Esker | last post: by
3 posts views Thread by Lynn | last post: by
3 posts views Thread by Robb Gilmore | last post: by
4 posts views Thread by Reuven Nisser | last post: by
4 posts views Thread by keithb | last post: by
4 posts views Thread by Eric Layman | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.