473,761 Members | 10,365 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

XML Deserialization (IXmlSerializab le implementation)

To whoever can help,

I've been having a problem with XML deserialization lately.

I needed to serialize and deserialze two objects which inherited from
Hashtable. Because IDictionary implementations cannot be serialized, I had
to take matters into my own hands by implementing a wrapper over the
Hashtable which implemted IXmlSerializabl e.

I called it XmlHashtable. It has, among other convenience methods, a method
called ReadXml(XmlRead er) and a method called WriteXml(XmlWri ter). This is
an abstract class which also contains two abstract properties which return
strings so I could have inheriting classes choose the names they wish for the
root element name and the name for individual items.

I implemented my own, because though I've seen code on the web which is
similar, I needed to be able to use actual objects as values, and not just
strings. This code works with any Type you wish to put into the Hashtable
that is available at runtime. I've tested it with both native Types and some
of my user defined types.

The code looks like this:
<code>
[XmlType( "XmlDict" )]
public abstract class XmlHashtable : Hashtable, IXmlSerializabl e {
/// <summary>
/// Returns the local name of the root node for the class. Implementing
/// classes must override this property.
/// </summary>
protected abstract string LocalName {get;}
/// <summary>
/// Returns the local name of the name of items in the dictionary.
/// Implementing classes must override this property.
/// </summary>
protected abstract string ItemType { get;}
/// <summary>
/// Generates an <see cref="XmlHashta ble"/> from its XML representation.
/// </summary>
/// <param name="reader">T he <see cref="XmlReader "/> from which the
/// object is deserialized</param>
public void ReadXml ( System.Xml.XmlR eader reader ) {
try {
string key = null;
object value = null;
Type type = null;

reader.ReadToFo llowing ( LocalName );
if ( reader.IsStartE lement ( LocalName ) ) {
reader.ReadStar tElement ( LocalName );

while ( reader.NodeType != XmlNodeType.End Element ) {
key = reader.GetAttri bute ( "Key" );
type = Type.GetType ( reader.GetAttri bute ( "Type" ) );
reader.ReadStar tElement ( ItemType );
reader.ReadStar tElement ( "Value" );
XmlSerializer serializer = new XmlSerializer ( type );
value = serializer.Dese rialize ( reader.ReadSubt ree( ) );
this.Add ( key, value );
reader.ReadEndE lement ( ); // Reading end node for Name
reader.ReadEndE lement ( ); // Reading end node for Value
reader.ReadEndE lement ( ); // Reading end node for
Element
reader.MoveToCo ntent ( );
}

reader.ReadEndE lement ( ); // Reading end root node
}
}

catch ( XmlException e ) {
throw new XmlException ( "XmlDictionary. ReadXml(XmlRead er)
reader pointing to invalid element", e );
}
}

/// <summary>
/// Converts an <see cref="XmlHashta ble"/> object into its XML
/// representation.
/// </summary>
/// <param name="writer">T he <see cref="XmlWriter "/> stream to which the
/// object is serialized</param>
public void WriteXml ( System.Xml.XmlW riter writer ) {
writer.WriteSta rtElement ( LocalName );
foreach ( DictionaryEntry de in this ) {
writer.WriteSta rtElement ( ItemType );
writer.WriteAtt ributeString ( "Key", de.Key.ToString ( ) );
writer.WriteAtt ributeString ( "Type", de.Value.GetTyp e (
).FullName );
writer.WriteSta rtElement ( "Value" );
XmlSerializer serializer = new XmlSerializer ( de.Value.GetTyp e
( ) );
serializer.Seri alize ( writer, de.Value );
writer.WriteEnd Element ( );
writer.WriteEnd Element ( );
}

writer.WriteEnd Element ( );
}
}
</code>

The inheriting classes must use the [XmlSchemaProvid er( "GetXmlSche ma" )]
attribute, which they do as shown here:

<code>
/// <summary>
/// Adds the XML schema to the <see cref="XmlSchema Set"/> and returns
/// the fully qualified name for the <see cref="AssetProp erties"/>
/// root element.
/// </summary>
/// <param name="set">The <see cref="XmlSchema Set"/> to add the schema
/// to</param>
/// <returns><see cref="XmlQualif iedName"/> representing the
/// schema for this type</returns>
public static XmlQualifiedNam e GetXmlSchema ( XmlSchemaSet set ) {
XmlSchemaAttrib ute attribute;
XmlSchemaSequen ce sequence;
XmlSchemaElemen t element;

XmlSchemaComple xType itemType = new XmlSchemaComple xType ( );
itemType.Name = ItemType + "Type";

// create the "Key" attribute and add it to the complex item type
attribute = new XmlSchemaAttrib ute ( );
attribute.Name = "Key";
attribute.Schem aTypeName = new XmlQualifiedNam e ( "string",
"http://www.w3.org/2001/XMLSchema" );
attribute.Use = XmlSchemaUse.Re quired;
itemType.Attrib utes.Add ( attribute );

// create the "Type" attribute and add it to the complex item type
attribute = new XmlSchemaAttrib ute ( );
attribute.Name = "Type";
attribute.Schem aTypeName = new XmlQualifiedNam e ( "string",
"http://www.w3.org/2001/XMLSchema" );
attribute.Use = XmlSchemaUse.Re quired;
itemType.Attrib utes.Add ( attribute );

sequence = new XmlSchemaSequen ce ( );

element = new XmlSchemaElemen t ( );
element.Name = "Value";
element.SchemaT ypeName = new XmlQualifiedNam e ( "anyType",
"http://www.w3.org/2001/XMLSchema" );

sequence.Items. Add ( element );
itemType.Partic le = sequence;

XmlSchemaComple xType assetProperties Type = new
XmlSchemaComple xType ( );
assetProperties Type.Name = LocalName + "Type";

// create "AssetPropertie sType" schema type for
"AssetPropertie s" element
sequence = new XmlSchemaSequen ce ( );
element = new XmlSchemaElemen t ( );
element.Name = XmlCoreTypes.As setProperties.I temType;
element.MaxOccu rsString = "unbounded" ;
element.MinOccu rsString = "0";
element.SchemaT ypeName = new XmlQualifiedNam e ( itemType.Name,
"http://mediaframe.com" );
sequence.Items. Add ( element );
assetProperties Type.Particle = sequence;

element = new XmlSchemaElemen t ( );
element.Name = LocalName;
element.SchemaT ypeName = new XmlQualifiedNam e (
assetProperties Type.Name, "http://mediaframe.com" );

// Generate the Schema element itself and set the necessary
properties
XmlSchema schema = new XmlSchema ( );
schema.TargetNa mespace = "http://mediaframe.com" ;
schema.Namespac es.Add ( "mf", "http://mediaframe.com" );
schema.Items.Ad d ( element );
schema.Items.Ad d ( itemType );
schema.Items.Ad d ( assetProperties Type );

// Add the schema to the set of schemas and compile it
set.XmlResolver = new XmlUrlResolver ( );
set.Add ( schema );
set.Compile ( );

//return element.Qualifi edName;
return assetProperties Type.QualifiedN ame;
}
</code>

So, serializing and deserializing one of these objects by itself works
perfectly. However, when I try to serialize an array of these objects and
then deserialize it, I only get the first one deserialized before it all
quits on me. The serialization works fine, I can see the XML by putting a
break point before deserializing.

I'm trying to use this in my web services, but it has the same issue whether
I serialize and deserialize manually (with the XmlSerializer) or use the web
services to do it all.

I'm just trying to figure out where I went wrong. Any tips would be
extremely useful.

Thanks,
John Glover
Mar 21 '06 #1
3 4998
Hi John,

Could you show me how you serialize and deserialize the array? I'm trying
to make a repro on my computer so that I can make a better troubleshooting .
Thanks!

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

Mar 22 '06 #2
Kevin,

I'm using the following code to serialize and deserialize which is pulled
from my test class for an object called AssetProperties which implements the
XmlHashtable abstract class from my first post:

<code>
[TestMethod ( )]
public void XmlArraySeriali zationTest ( ) {
AssetProperties[ ] objA = new AssetProperties[ ] {
<put some code here to initialize the array> };

XmlSerializer serializer = new XmlSerializer ( typeof ( AssetProperties[
] ) );
StringWriter writer = new StringWriter ( );
serializer.Seri alize ( writer, objA );
StringReader reader = new StringReader ( writer.ToString ( ) );

AssetProperties[ ] objB = (AssetPropertie s[ ])serializer.Des erialize (
reader );

Assert.AreEqual ( objA.Length, objB.Length,
objA.GetType ( ).ToString ( ) + " failed XML serialization and
deserialization -- arrays not the same size." );
for ( int i = 0; i < objA.Length; ++i ) {
Assert.AreEqual ( objA[i], objB[i], objA.GetType ( ).ToString ( ) +
" failed XML serialization and deserialization ." );
}
}
</code>

However, I think I have figured out what the problem is. Well, at least I
know what to do to make it stop, but I still have a problem. I fixed the
problem by adding a line to my ReadXml(XmlRead er) method so that it read an
extra end element at the end, like this:

<code>
/// <summary>
/// Generates an <see cref="XmlHashta ble"/> from its XML representation.
/// </summary>
/// <param name="reader">T he <see cref="XmlReader "/> from which the
/// object is deserialized</param>
public void ReadXml ( System.Xml.XmlR eader reader ) {
try {
string key = null;
object value = null;
Type type = null;

reader.ReadToFo llowing ( LocalName );
if ( reader.IsStartE lement ( LocalName ) ) {
reader.ReadStar tElement ( LocalName );

while ( reader.NodeType != XmlNodeType.End Element ) {
key = reader.GetAttri bute ( "Key" );
type = Type.GetType ( reader.GetAttri bute ( "Type" ) );
reader.ReadStar tElement ( ItemType );
reader.ReadStar tElement ( "Value" );
XmlSerializer serializer = new XmlSerializer ( type );
value = serializer.Dese rialize ( reader.ReadSubt ree( ) );
this.Add ( key, value );
reader.ReadEndE lement ( ); // Reading end node for node inside Value
reader.ReadEndE lement ( ); // Reading end node for Value
reader.ReadEndE lement ( ); // Reading end node for Property
reader.MoveToCo ntent ( );
}
reader.ReadEndE lement( ); // Reading end node for Element
reader.ReadEndE lement( ); // Reading extra funny end node
</code>

But the problem still remains that I have this funny root element. I
believe the problem is that my schema is not turning out the way I would
like. The schema looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tmf="http ://thomson.com/MediaFrame"
targetNamespace ="http://thomson.com/MediaFrame"
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="AssetProp erties" type="tmf:Asset PropertiesType" />

<xs:complexTy pe name="PropertyT ype">
<xs:sequence>
<xs:element name="Value" type="xs:anyTyp e" />
</xs:sequence>
<xs:attribute name="Key" type="xs:string " use="required" />
<xs:attribute name="Type" type="xs:string " use="required" />
</xs:complexType>

<xs:complexTy pe name="AssetProp ertiesType">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbo unded" name="Property"
type="tmf:Prope rtyType" />
</xs:sequence>
</xs:complexType>

</xs:schema>

So I would have assumed that the root element would be a <AssetPropertie s>,
but it is not. The root element is <AssetPropertie sType>. This is not what
I expect.

When I manipulate the code to build a schema like this:

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:tns="http ://thomson.com/MediaFrame"
attributeFormDe fault="unqualif ied" elementFormDefa ult="qualified"
targetNamespace ="http://thomson.com/MediaFrame"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="AssetProp erties">
<xs:complexType >
<xs:sequence>
<xs:element maxOccurs="unbo unded" name="Property" >
<xs:complexType >
<xs:sequence>
<xs:element name="Value" type="xs:string " />
</xs:sequence>
<xs:attribute name="Key" type="xs:string " use="required" />
<xs:attribute name="Type" type="xs:string " use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

I get all kinds of errors about a name being required.

Is there a good reference for how to build an XML schema using code from the
XmlSchema namespace?

Any suggestions about what I've done wrong would be extremely helpful.

Thanks,
John

"Kevin Yu [MSFT]" wrote:
Hi John,

Could you show me how you serialize and deserialize the array? I'm trying
to make a repro on my computer so that I can make a better troubleshooting .
Thanks!

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

Mar 22 '06 #3
Hi John,

Have you tried to use XmlRootAttribut e for the AssetProperties class?

[XmlRoot(Namespa ce = "www.contoso.co m",
ElementName = "AsseteProperti es",
DataType = "string",
IsNullable=true )]

I think this will help you to control the root element name. For more
information, please check the following link:

http://msdn.microsoft.com/library/de...us/cpref/html/
frlrfsystemxmls erializationxml rootattributecl asstopic.asp

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

Mar 24 '06 #4

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

Similar topics

1
2170
by: mattoc | last post by:
Happy new year to all. I have a strange error that I've been trying for a while now to fathom.. Basically I have a hierarchy of state classes that I need to serialize to XML. Some of them can contain Exceptions, so I've decided to implement IXmlSerializable to get round the fact that Exception is not serializable.
0
1899
by: Thomas D. | last post by:
Situation: --------------------------- I have an 'export'-wrapper to my regular objects. For each regular object there is also an export object. An export object derives from the regular object and has for each property in the base object an extra boolean property. That extra properties tells wether to include the base property in the final export (= webservice) or not. That is because not all the properties may be exposed all the time...
8
3467
by: ashoksrini | last post by:
Hi All, I have the below requirement and would like to get some feeback from the group on the best way to implement: 1. I have WSDL defined exposing few web services. 2. We dont have a requirement to have a server web service class. (reasons below) 3. I want to develop something like this - when client makes a web service call, on the server I can intercept the SOAP message (XML doc itself),
1
4422
by: Thomas D. | last post by:
Hello all, I'm using the IXmlSerializable interface for a project and encounter some problems when testing my webservice in a client application. I know this interface is undocumented and not intended for use, but I think this is the only solution for my situation. I searched the web, in the hope finding the answer, without any luck, so my final hope is with you. Let me explain the situation: I have an 'export'-wrapper to my regular...
0
1075
by: Chris Szabo | last post by:
Good afternoon everyone. I'm running into a problem deserializing a stream using the XmlSerializer. A stored procedure returns the following from SQL Server: <Student StudentId="1" Status="1" Gpa="3.50"> <Person Id="1" FirstName="FirstName0" LastName="LastName0" MiddleInitial="W"/> </Student> In my code, person is the base class and student extends it. When I
1
831
by: Peter Nofelt | last post by:
Hey All, I am having issue with serializing a class and its base class using ..net 2.0. I am using IXmlSerializable I've provided code displaying my at the bottom of this post. Thanks ahead of time for any help or feedback. Cheers, Peter
5
1964
by: Ruben | last post by:
Hi! Is there a way to figure out, if the constructor or the Set-methods of fields are called by the XML-deserilization or by other calls? I would like to bind special behaviour to my class when those methods are called by the deserializer... Thank you! Ruben
3
5278
by: =?Utf-8?B?S2VubmV0aCBILiBCcmFubmlnYW4=?= | last post by:
Hello, I was wondering if there is a way to have the contents of an XML element that contains HTML to be deserialized into the cooresponding string property without the HTML tags being surronded by CDATA? <?xml version="1.0" encoding="UTF-8" ?> <introduction> <header> <h1>Helping you achieve the natural look you want</h1> </header>
2
1116
by: xlar54 | last post by:
Lets say I have an xml document that reads: <Book> <ID> <Title>SomeTitle</Title> <ISBN>12345</ISBN> </ID> </Book> But I want to deserialize it to an object that looks like:
0
9531
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9345
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10115
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9957
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8780
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5229
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 last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5373
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
3456
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2752
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 can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.