By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,851 Members | 1,118 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,851 IT Pros & Developers. It's quick & easy.

How do you prevent null elements from being serialized?

P: n/a
I am using complex types in order to support serialization/deserialization
of floating point numbers, since floating points can't be null.
I've seen how to suppress attributes that are "not specified", such as
having a float member called Value, and a bool member called ValueSpecified.
This instructs the XML Serializer to omit that attribute altogether if it
wasn't "Specified". But how can I tell it to omit the XML element
altogether?
Here's the problem:
I deserialize an object that looks like this:
<person>

<name>Joe</name>

<age>37</age>

</person>

When deserialized, I get an object of type person, with a field age of type
floatType which has Value = 37 and ValueSpecified = false.
If I change name to "Bob" (p.name = "Bob"), and then immediately serialize
that object to XML, I get:
<person>

<name>Bob</name>

<age />

</person>

This indicates that age should now be null (if I pass this off to a SOAP
server for instance), or if that value is not allowed to be nulled, then I
get a SOAP exception.
If I explicitly set p.age.ValueSpecified = true or set p.age.Value = 36
(which implicitly sets ValueSpecified to true)
Then I get the expected
<person>

<name>Bob</name>

<age>36</age>

</person>

What I would like to see happen is if ValueSpecified is false, then just
leave that element off altogether. Is there a way to do this?
Thanks for your help

Kenny
Nov 12 '05 #1
Share this Question
Share on Google+
1 Reply


P: n/a
Kenny, you don't show your code, but something fishy is going on.

1. De-serializing from

<person>
<name>Joe</name>
<age>37</age>
</person>

....I get name=Joe, Age=37 and AgeSpecified = true (not false as you report).

Also, changing the Name from Joe to Bob should not affect Age or
AgeSpecified, as you report. Also, changing Age does not directly affect
AgeSpecified. These things are true, unless you have put some non-default
handling in the property getter/setter.

What I would like to see happen is if ValueSpecified is false, then just
leave that element off altogether. Is there a way to do this?
This is the default behavior?, so I don't understand why you are asking
this. The code enclosed below demonstrates this, and some other interesting
things in XML serialization.

In fact you have to do something special in order to get an empty element
(eg "<Age />") to appear in an XML stream output from the .NET XML
Serializer. If you use isnullable:=True in the XmlElementAttribute, you
will get <Age xsi:nil="true" />, which is not quite the same thing.
-Dino


----- Begin Code -----
// XmlIgnoreTest.cs
//
// Exercises some of the XmlIgnore stuff
//
// compile with:
//
// (c) Ionic Shade
// Wed, 17 Nov 2004 10:02
//

using System.IO;
using System.Xml.Serialization;
// This is the default class generated from xsd.exe
[System.Xml.Serialization.XmlRootAttribute(Namespac e="", IsNullable=false)]
public class Person {

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Name;

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSchemaForm.Unqualified)]
public System.Single Age;

[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool AgeSpecified;
}


namespace Ionic {

public class XmlTextWriterFormattedNoDeclaration :
System.Xml.XmlTextWriter {
public XmlTextWriterFormattedNoDeclaration (System.IO.TextWriter w) :
base(w) { Formatting= System.Xml.Formatting.Indented;}
public override void WriteStartDocument () { }
}
public class TestDriver {

static void Main(string[] args) {

try {

string OriginalXml=
"<Person>\n" +
" <Name>Joe</Name>\n" +
" <Age>37</Age>\n" +
"</Person>\n" +
"";

System.Console.WriteLine("\n====================== ======================\nOriginal
XML:\n"+ OriginalXml);

XmlSerializer s1 = new XmlSerializer(typeof(Person));
Person p= null;
using (System.IO.StringReader sr= new
System.IO.StringReader(OriginalXml)) {
p = (Person) s1.Deserialize(sr);
}

// suppress default namespace entries in the root elt
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add( "", "" );

// use a custom TextWriter to suppress the XML declaration

System.Console.WriteLine("\n====================== ======================\nOriginal
values:");
s1.Serialize(new
XmlTextWriterFormattedNoDeclaration(System.Console .Out), p, ns);
System.Console.WriteLine("\n");

System.Console.WriteLine("\n====================== ======================\nChanging
the name does not change the age:");
p.Name= "Bob";
s1.Serialize(new
XmlTextWriterFormattedNoDeclaration(System.Console .Out), p, ns);
System.Console.WriteLine("\n");
System.Console.WriteLine("\n====================== ======================\nUn-specifying
the Age results in this:");
p.AgeSpecified= false;
s1.Serialize(new
XmlTextWriterFormattedNoDeclaration(System.Console .Out), p, ns);
System.Console.WriteLine("\n");
string OriginalXml2=
"<Person>\n" +
" <Name>Shirley</Name>\n" +
" <Age />\n" +
"</Person>\n" +
"";
System.Console.WriteLine("\n====================== ======================\nCase
2: Original XML:\n"+ OriginalXml2);
p=null;
try {
System.Console.WriteLine("\n(De-serializing from this will
fail...)\n");
using (System.IO.StringReader sr= new
System.IO.StringReader(OriginalXml2)) {
p = (Person) s1.Deserialize(sr);
}
}
catch (System.InvalidOperationException ex1) {
System.Console.WriteLine("As Expected, an Exception was generated:
" + ex1);

}

if (p!= null) {
System.Console.WriteLine("\n====================== ======================\nOriginal
values:");
s1.Serialize(new
XmlTextWriterFormattedNoDeclaration(System.Console .Out), p, ns);
System.Console.WriteLine("\n");
}

p= new Person();
p.Name= "Henry";
System.Console.WriteLine("\n====================== ======================\nNew
Instance, setting only Name:");
s1.Serialize(new
XmlTextWriterFormattedNoDeclaration(System.Console .Out), p, ns);
System.Console.WriteLine("\n");

p.Age= 66;
System.Console.WriteLine("\n====================== ======================\nalso
setting Ageon that instance:");
s1.Serialize(new
XmlTextWriterFormattedNoDeclaration(System.Console .Out), p, ns);
System.Console.WriteLine("\n");

p.AgeSpecified= true;
System.Console.WriteLine("\n====================== ======================\nand
now setting AgeSpecified:");
s1.Serialize(new
XmlTextWriterFormattedNoDeclaration(System.Console .Out), p, ns);
System.Console.WriteLine("\n");

}
catch (System.Exception e1) {
System.Console.WriteLine("Exception!\n" + e1);
}
}
}
}

----- End Code -----
"Kenny Mullican" <no***********@nowayemonarch.net> wrote in message
news:%2******************@TK2MSFTNGP11.phx.gbl...I am using complex types in order to support serialization/deserialization
of floating point numbers, since floating points can't be null.
I've seen how to suppress attributes that are "not specified", such as
having a float member called Value, and a bool member called
ValueSpecified. This instructs the XML Serializer to omit that attribute
altogether if it wasn't "Specified". But how can I tell it to omit the
XML element altogether?
Here's the problem:
I deserialize an object that looks like this:
<person>

<name>Joe</name>

<age>37</age>

</person>

When deserialized, I get an object of type person, with a field age of
type floatType which has Value = 37 and ValueSpecified = false.
If I change name to "Bob" (p.name = "Bob"), and then immediately serialize
that object to XML, I get:
<person>

<name>Bob</name>

<age />

</person>

This indicates that age should now be null (if I pass this off to a SOAP
server for instance), or if that value is not allowed to be nulled, then I
get a SOAP exception.
If I explicitly set p.age.ValueSpecified = true or set p.age.Value = 36
(which implicitly sets ValueSpecified to true)
Then I get the expected
<person>

<name>Bob</name>

<age>36</age>

</person>

What I would like to see happen is if ValueSpecified is false, then just
leave that element off altogether. Is there a way to do this?
Thanks for your help

Kenny

Nov 12 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.