473,503 Members | 1,635 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

XmlSerializer - XmlTextReader vs. XmlNodeReader

I've run across a strange behaviour with XmlSerializer that I'm unable to explain. I came across this while trying to use XmlSerializer to deserialize from a the details of a SoapException. This should have worked fine since the class in question was already being serialized and deserialized as part of a Web service interface. What I found was that by deserializing from an XmlNodeReader instead of an XmlTextReader, XML Serialization doesn't work the same way as when it deserialized from an XmlTextReader.

This is easily reproduced with the following C# code:

using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;

public class MyClass
{
public ArrayList Values = new ArrayList();
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
MyClass myClass1 = new MyClass();
myClass1.Values.Add(123);
myClass1.Values.Add("abc");

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
XmlWriter writer = new XmlTextWriter("temp.xml", System.Text.Encoding.UTF8);
serializer.Serialize(writer, myClass1);
writer.Close();

// Deserializing using an XmlTextReader works fine
MyClass myClass2 = (MyClass)serializer.Deserialize(new XmlTextReader("temp.xml"));
foreach (object value in myClass2.Values) Console.WriteLine(value.ToString());
Console.ReadLine();

// Deserializing using an XmlNodeReader over the same document doesn't work
XmlDocument doc = new XmlDocument();
doc.Load("temp.xml");
MyClass myClass3 = (MyClass)serializer.Deserialize(new XmlNodeReader(doc));
foreach (object value in myClass3.Values) Console.WriteLine(value.ToString());
Console.ReadLine();
}
}

The "temp.xml" file will contain the following:

<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Values>
<anyType xsi:type="xsd:int">123</anyType>
<anyType xsi:type="xsd:string">abc</anyType>
</Values>
</MyClass>

The output will be:

123
abc

System.Xml.XmlNode[]
System.Xml.XmlNode[]

It would seem to me that this has got to be a bug since the XML infoset that XmlSerializer is consuming should be identical whether it is coming from an XmlTextReader or XmlNodeReader.

There is an obvious workaround (serialize the XmlNode to a MemoryStream, then deserialize from it using an XmlTextReader). Somehow writing then re-parsing the XML that has already been loaded into a DOM seems very ugly and unncessary. Can someone suggest an alternative solution, or an explanation for this behaviour?

Andy
Nov 12 '05 #1
4 11348
The problem is you are de-serializing into an ArrayList, and you haven't provided any hints to the serializer as to the types of the items in that list.
At De-serialization time, the runtime doesn't know what to de-serialize the various xml nodes into. When you de-serialize from a XmlTextReader, the serializer uses the xsi:type as guesses. When you de-serialize from an XmlNodeReader, you get (surprise!) XmlNodes, which correspond to the attributes and InnerText in that node.

To address this you could simply add some hints to the ArrayList Values. Eg:

public class MyClass
{
[XmlArray("Values")]
[XmlArrayItem("StringValue",typeof(System.String))]
[XmlArrayItem("IntValue",typeof(System.Int32))]

public ArrayList Values = new ArrayList();
}
Doing this you will get the same results using either Reader. If you have objects of completely arbitrary type in the arraylist, then you will want to add an
[XmlArrayItem("Unknown",typeof(System.Object))]

to the list of attributes. This will revert to the behavior of getting an XmlNode[] for that particular arraylist item.

-Dino
"Andy Neilson" <aneilsonNoSpam69AthotmailDotcom> wrote in message news:%2******************@TK2MSFTNGP09.phx.gbl...
I've run across a strange behaviour with XmlSerializer that I'm unable to explain. I came across this while trying to use XmlSerializer to deserialize from a the details of a SoapException. This should have worked fine since the class in question was already being serialized and deserialized as part of a Web service interface. What I found was that by deserializing from an XmlNodeReader instead of an XmlTextReader, XML Serialization doesn't work the same way as when it deserialized from an XmlTextReader.

This is easily reproduced with the following C# code:

using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;

public class MyClass
{
public ArrayList Values = new ArrayList();
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
MyClass myClass1 = new MyClass();
myClass1.Values.Add(123);
myClass1.Values.Add("abc");

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
XmlWriter writer = new XmlTextWriter("temp.xml", System.Text.Encoding.UTF8);
serializer.Serialize(writer, myClass1);
writer.Close();

// Deserializing using an XmlTextReader works fine
MyClass myClass2 = (MyClass)serializer.Deserialize(new XmlTextReader("temp.xml"));
foreach (object value in myClass2.Values) Console.WriteLine(value.ToString());
Console.ReadLine();

// Deserializing using an XmlNodeReader over the same document doesn't work
XmlDocument doc = new XmlDocument();
doc.Load("temp.xml");
MyClass myClass3 = (MyClass)serializer.Deserialize(new XmlNodeReader(doc));
foreach (object value in myClass3.Values) Console.WriteLine(value.ToString());
Console.ReadLine();
}
}

The "temp.xml" file will contain the following:

<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Values>
<anyType xsi:type="xsd:int">123</anyType>
<anyType xsi:type="xsd:string">abc</anyType>
</Values>
</MyClass>

The output will be:

123
abc

System.Xml.XmlNode[]
System.Xml.XmlNode[]

It would seem to me that this has got to be a bug since the XML infoset that XmlSerializer is consuming should be identical whether it is coming from an XmlTextReader or XmlNodeReader.

There is an obvious workaround (serialize the XmlNode to a MemoryStream, then deserialize from it using an XmlTextReader). Somehow writing then re-parsing the XML that has already been loaded into a DOM seems very ugly and unncessary. Can someone suggest an alternative solution, or an explanation for this behaviour?

Andy
Nov 12 '05 #2
The problem is you are de-serializing into an ArrayList, and you haven't provided any hints to the serializer as to the types of the items in that list.
At De-serialization time, the runtime doesn't know what to de-serialize the various xml nodes into. When you de-serialize from a XmlTextReader, the serializer uses the xsi:type as guesses. When you de-serialize from an XmlNodeReader, you get (surprise!) XmlNodes, which correspond to the attributes and InnerText in that node.

To address this you could simply add some hints to the ArrayList Values. Eg:

public class MyClass
{
[XmlArray("Values")]
[XmlArrayItem("StringValue",typeof(System.String))]
[XmlArrayItem("IntValue",typeof(System.Int32))]

public ArrayList Values = new ArrayList();
}
Doing this you will get the same results using either Reader. If you have objects of completely arbitrary type in the arraylist, then you will want to add an
[XmlArrayItem("Unknown",typeof(System.Object))]

to the list of attributes. This will revert to the behavior of getting an XmlNode[] for that particular arraylist item.

-Dino
"Andy Neilson" <aneilsonNoSpam69AthotmailDotcom> wrote in message news:%2******************@TK2MSFTNGP09.phx.gbl...
I've run across a strange behaviour with XmlSerializer that I'm unable to explain. I came across this while trying to use XmlSerializer to deserialize from a the details of a SoapException. This should have worked fine since the class in question was already being serialized and deserialized as part of a Web service interface. What I found was that by deserializing from an XmlNodeReader instead of an XmlTextReader, XML Serialization doesn't work the same way as when it deserialized from an XmlTextReader.

This is easily reproduced with the following C# code:

using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;

public class MyClass
{
public ArrayList Values = new ArrayList();
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
MyClass myClass1 = new MyClass();
myClass1.Values.Add(123);
myClass1.Values.Add("abc");

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
XmlWriter writer = new XmlTextWriter("temp.xml", System.Text.Encoding.UTF8);
serializer.Serialize(writer, myClass1);
writer.Close();

// Deserializing using an XmlTextReader works fine
MyClass myClass2 = (MyClass)serializer.Deserialize(new XmlTextReader("temp.xml"));
foreach (object value in myClass2.Values) Console.WriteLine(value.ToString());
Console.ReadLine();

// Deserializing using an XmlNodeReader over the same document doesn't work
XmlDocument doc = new XmlDocument();
doc.Load("temp.xml");
MyClass myClass3 = (MyClass)serializer.Deserialize(new XmlNodeReader(doc));
foreach (object value in myClass3.Values) Console.WriteLine(value.ToString());
Console.ReadLine();
}
}

The "temp.xml" file will contain the following:

<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Values>
<anyType xsi:type="xsd:int">123</anyType>
<anyType xsi:type="xsd:string">abc</anyType>
</Values>
</MyClass>

The output will be:

123
abc

System.Xml.XmlNode[]
System.Xml.XmlNode[]

It would seem to me that this has got to be a bug since the XML infoset that XmlSerializer is consuming should be identical whether it is coming from an XmlTextReader or XmlNodeReader.

There is an obvious workaround (serialize the XmlNode to a MemoryStream, then deserialize from it using an XmlTextReader). Somehow writing then re-parsing the XML that has already been loaded into a DOM seems very ugly and unncessary. Can someone suggest an alternative solution, or an explanation for this behaviour?

Andy
Nov 12 '05 #3
I think you are missing my point. I can't think of any reason why the identical XML infoset represented by an XmlReader would be treated differently depending on whether it is an XmlTextReader reading from a FileStream, or an XmlNodeReader over an XmlDocument. In both cases, the XmlSerializer should have the the identical xsi:type information available to it, so why is it ignored in the XmlNodeReader case?
The problem is you are de-serializing into an ArrayList, and you haven't provided any hints to the serializer as to the types of the items in that list. <<<
There is an excellent hint in the XML in the form of the xsi:type attribute that the XmlSerializer has put there for just that purpose when I serialized the ArrayList. In the XmlTextReader case, the XmlSerializer does exactly what I expect in that it uses its default mappings from xsi:type to simple types, so there should be no need to use type-specific element names. If the XmlTextReader takes the hint, the XmlNodeReader should do so as well!
When you de-serialize from an XmlNodeReader, you get (surprise!) XmlNodes, which correspond to the attributes and InnerText in that node.<<<


I have no idea what you mean by that statement. Regardless of derived type of the XmlReader you are using, the interface presents a forward-only cursor over XmlNodes. Why would an XmlNodeReader present a different set of nodes than XmlTextReader? If XmlNodeReader doesn't present the same nodes as XmlTextReader, could you explain what the difference is? It seems like an important difference that is not at all obvious.

Andy

"Dino Chiesa [Microsoft]" <di****@online.microsoft.com> wrote in message news:uy**************@TK2MSFTNGP09.phx.gbl...
The problem is you are de-serializing into an ArrayList, and you haven't provided any hints to the serializer as to the types of the items in that list.
At De-serialization time, the runtime doesn't know what to de-serialize the various xml nodes into. When you de-serialize from a XmlTextReader, the serializer uses the xsi:type as guesses. When you de-serialize from an XmlNodeReader, you get (surprise!) XmlNodes, which correspond to the attributes and InnerText in that node.

To address this you could simply add some hints to the ArrayList Values. Eg:

public class MyClass
{
[XmlArray("Values")]
[XmlArrayItem("StringValue",typeof(System.String))]
[XmlArrayItem("IntValue",typeof(System.Int32))]

public ArrayList Values = new ArrayList();
}
Doing this you will get the same results using either Reader. If you have objects of completely arbitrary type in the arraylist, then you will want to add an
[XmlArrayItem("Unknown",typeof(System.Object))]

to the list of attributes. This will revert to the behavior of getting an XmlNode[] for that particular arraylist item.

-Dino
"Andy Neilson" <aneilsonNoSpam69AthotmailDotcom> wrote in message news:%2******************@TK2MSFTNGP09.phx.gbl...
I've run across a strange behaviour with XmlSerializer that I'm unable to explain. I came across this while trying to use XmlSerializer to deserialize from a the details of a SoapException. This should have worked fine since the class in question was already being serialized and deserialized as part of a Web service interface. What I found was that by deserializing from an XmlNodeReader instead of an XmlTextReader, XML Serialization doesn't work the same way as when it deserialized from an XmlTextReader.

This is easily reproduced with the following C# code:

using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;

public class MyClass
{
public ArrayList Values = new ArrayList();
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
MyClass myClass1 = new MyClass();
myClass1.Values.Add(123);
myClass1.Values.Add("abc");

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
XmlWriter writer = new XmlTextWriter("temp.xml", System.Text.Encoding.UTF8);
serializer.Serialize(writer, myClass1);
writer.Close();

// Deserializing using an XmlTextReader works fine
MyClass myClass2 = (MyClass)serializer.Deserialize(new XmlTextReader("temp.xml"));
foreach (object value in myClass2.Values) Console.WriteLine(value.ToString());
Console.ReadLine();

// Deserializing using an XmlNodeReader over the same document doesn't work
XmlDocument doc = new XmlDocument();
doc.Load("temp.xml");
MyClass myClass3 = (MyClass)serializer.Deserialize(new XmlNodeReader(doc));
foreach (object value in myClass3.Values) Console.WriteLine(value.ToString());
Console.ReadLine();
}
}

The "temp.xml" file will contain the following:

<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Values>
<anyType xsi:type="xsd:int">123</anyType>
<anyType xsi:type="xsd:string">abc</anyType>
</Values>
</MyClass>

The output will be:

123
abc

System.Xml.XmlNode[]
System.Xml.XmlNode[]

It would seem to me that this has got to be a bug since the XML infoset that XmlSerializer is consuming should be identical whether it is coming from an XmlTextReader or XmlNodeReader.

There is an obvious workaround (serialize the XmlNode to a MemoryStream, then deserialize from it using an XmlTextReader). Somehow writing then re-parsing the XML that has already been loaded into a DOM seems very ugly and unncessary. Can someone suggest an alternative solution, or an explanation for this behaviour?

Andy
Nov 12 '05 #4
I think you are missing my point. I can't think of any reason why the identical XML infoset represented by an XmlReader would be treated differently depending on whether it is an XmlTextReader reading from a FileStream, or an XmlNodeReader over an XmlDocument. In both cases, the XmlSerializer should have the the identical xsi:type information available to it, so why is it ignored in the XmlNodeReader case?
The problem is you are de-serializing into an ArrayList, and you haven't provided any hints to the serializer as to the types of the items in that list. <<<
There is an excellent hint in the XML in the form of the xsi:type attribute that the XmlSerializer has put there for just that purpose when I serialized the ArrayList. In the XmlTextReader case, the XmlSerializer does exactly what I expect in that it uses its default mappings from xsi:type to simple types, so there should be no need to use type-specific element names. If the XmlTextReader takes the hint, the XmlNodeReader should do so as well!
When you de-serialize from an XmlNodeReader, you get (surprise!) XmlNodes, which correspond to the attributes and InnerText in that node.<<<


I have no idea what you mean by that statement. Regardless of derived type of the XmlReader you are using, the interface presents a forward-only cursor over XmlNodes. Why would an XmlNodeReader present a different set of nodes than XmlTextReader? If XmlNodeReader doesn't present the same nodes as XmlTextReader, could you explain what the difference is? It seems like an important difference that is not at all obvious.

Andy

"Dino Chiesa [Microsoft]" <di****@online.microsoft.com> wrote in message news:uy**************@TK2MSFTNGP09.phx.gbl...
The problem is you are de-serializing into an ArrayList, and you haven't provided any hints to the serializer as to the types of the items in that list.
At De-serialization time, the runtime doesn't know what to de-serialize the various xml nodes into. When you de-serialize from a XmlTextReader, the serializer uses the xsi:type as guesses. When you de-serialize from an XmlNodeReader, you get (surprise!) XmlNodes, which correspond to the attributes and InnerText in that node.

To address this you could simply add some hints to the ArrayList Values. Eg:

public class MyClass
{
[XmlArray("Values")]
[XmlArrayItem("StringValue",typeof(System.String))]
[XmlArrayItem("IntValue",typeof(System.Int32))]

public ArrayList Values = new ArrayList();
}
Doing this you will get the same results using either Reader. If you have objects of completely arbitrary type in the arraylist, then you will want to add an
[XmlArrayItem("Unknown",typeof(System.Object))]

to the list of attributes. This will revert to the behavior of getting an XmlNode[] for that particular arraylist item.

-Dino
"Andy Neilson" <aneilsonNoSpam69AthotmailDotcom> wrote in message news:%2******************@TK2MSFTNGP09.phx.gbl...
I've run across a strange behaviour with XmlSerializer that I'm unable to explain. I came across this while trying to use XmlSerializer to deserialize from a the details of a SoapException. This should have worked fine since the class in question was already being serialized and deserialized as part of a Web service interface. What I found was that by deserializing from an XmlNodeReader instead of an XmlTextReader, XML Serialization doesn't work the same way as when it deserialized from an XmlTextReader.

This is easily reproduced with the following C# code:

using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;

public class MyClass
{
public ArrayList Values = new ArrayList();
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
MyClass myClass1 = new MyClass();
myClass1.Values.Add(123);
myClass1.Values.Add("abc");

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
XmlWriter writer = new XmlTextWriter("temp.xml", System.Text.Encoding.UTF8);
serializer.Serialize(writer, myClass1);
writer.Close();

// Deserializing using an XmlTextReader works fine
MyClass myClass2 = (MyClass)serializer.Deserialize(new XmlTextReader("temp.xml"));
foreach (object value in myClass2.Values) Console.WriteLine(value.ToString());
Console.ReadLine();

// Deserializing using an XmlNodeReader over the same document doesn't work
XmlDocument doc = new XmlDocument();
doc.Load("temp.xml");
MyClass myClass3 = (MyClass)serializer.Deserialize(new XmlNodeReader(doc));
foreach (object value in myClass3.Values) Console.WriteLine(value.ToString());
Console.ReadLine();
}
}

The "temp.xml" file will contain the following:

<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Values>
<anyType xsi:type="xsd:int">123</anyType>
<anyType xsi:type="xsd:string">abc</anyType>
</Values>
</MyClass>

The output will be:

123
abc

System.Xml.XmlNode[]
System.Xml.XmlNode[]

It would seem to me that this has got to be a bug since the XML infoset that XmlSerializer is consuming should be identical whether it is coming from an XmlTextReader or XmlNodeReader.

There is an obvious workaround (serialize the XmlNode to a MemoryStream, then deserialize from it using an XmlTextReader). Somehow writing then re-parsing the XML that has already been loaded into a DOM seems very ugly and unncessary. Can someone suggest an alternative solution, or an explanation for this behaviour?

Andy
Nov 12 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
1608
by: Zion Zadik | last post by:
Dear all, I have a set of c# data classes which i need to fill their data from xml files. serialization looks to be the best way to accomplish this task. Since the data classes are compiled and...
16
9490
by: Bob Rock | last post by:
Hello, when serializing an array of elements of a class Classname using XmlSerializer.Serialize() I get an XML like the following: <?xml version="1.0"> <ArrayOfClassname> ....... ..........
2
942
by: magister | last post by:
Hello I got this working but it is not how I really want it, basically I have an xml file which has a root of <test> and can be filled with 3 different types of <question> elements with different...
3
10371
by: stax | last post by:
Hello, can somebody tell me how to serialize/deserialize a object containing a multi line string using the XmlSerializer class. One of the both windows linefeed chars get dumped somewhere down...
0
2269
by: William Stacey [MVP] | last post by:
Had a method that got some string info from mp3 tags in N files and serializes this class and deserializes at other side. Works ok except sometimes get chars that choke the XmlSerializer. After...
3
1760
by: Schorschi | last post by:
The following code works fine until I check the .CanDeserialize flag The exact same code in C# works, but in VB .NET? AUGH! HELP! ---------------------------------- Public Function...
1
5106
by: Yewen Tang | last post by:
I have a schema file datamodel.xsd, element "properties" is declared as a type of "baseProperty". The schema file also defines "derivedProperty" is a derived type of "baseProperty". <?xml...
0
2004
by: PSingh | last post by:
Hi, I know this is a frequently asked question but have tried several combinations and cant seem to figure this out. I am serializing my object as follows: XmlSerializer serializer = new...
6
3689
by: Andrew | last post by:
I am using an XmlSerializer to save some settings and I have discovered that when a string is saved containing a cr+nl it is replaced with just a newline when loading back in. I am no expert with...
0
7086
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7280
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7332
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
5014
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4673
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3167
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3154
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
736
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
382
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.