BizTalk Utilities CV ,   Jobs ,   Code library
 
Go to the front page to continue learning about XML or select below:

Contents

ReBlogger Contents

Previous posts in .NET XML, System.XML

 
 
Page 17331 of 20224

A Cry for Help (AKA, Implementing a XML Schema Provider)

Blogger : John Bristowes Weblog
All posts : All posts by John Bristowes Weblog
Category : .NET XML, System.XML
Blogged date : 2005 May 23

I`ve been having a lot of fun playing around with all the new goop in the .NET Framework 2.0 recently. Although my focus has been mostly on what`s new in the ASMX stack, I`ve also been looking at XML serialization.

As part of my demo code for TechEd 2005, I`ll be showing how to implement the interface, System.Xml.Serialization.IXmlSerializable for a type. This interface allows you to control the XML serialization/deserialization process in a streaming context. Also, I`ll be showing how to implement an XML schema provider. An XML schema provider is basically a method you delegate that controls how your schema will look when it`s generated by tools like wsdl.exe.

On the surface, XML serialization and XML schema generation aren`t too difficult. That is, until you try to do something a little more funky.

I`ve hit a snag in my implementation for a XML schema provider. The purpose of this blog entry is to solicit any help from you (the reader). As it stands right now, I`m stuck and can`t seem to find an adequate solution. But before I describe my problem, I should probably provide some context for those of you who don`t know what I`m talking about.

The .NET Framework 2.0 dramatically improves the infrastructure for controlling XML serialization and XML schema generation. It achieves this by supporting the interface, System.Xml.Serialization.IXmlSerializable. Some of you will recognize this interface. It`s the interface used by the System.Data.DataSet to control its serialization process to and from XML. In the .NET Framework 1.0/1.1, this interface was unsupported and undocumented. However, a few brave souls were able to figure out that this interface was ideal for controlling the XML serialization process. By implementing this interface, developers had finer control over how this process occurred.

At this point you might be asking, "What about all the XML serialization attributes we have Can`t they do the job" The answer is yes and no. Yes, the XML serialization attributes found in the System.Xml.Serialization (i.e. XmlTypeAttribute, XmlIgnoreAttribute) can do the job. However, they are somewhat limited. Let`s take a look at an example. Assume the following class:

public class Person
{ string _name; public string Name
{ get; set; } }

Without any modification, an instance of this type will serialize as follows:

< Person>
    <
Name>...Name>
Person>> >

Now, what if I want to modify how the XML looks Well, I can simply place an XML serialization attribute on the class like so:>

public class Person
{ string _name; [XmlElement("PersonName")] public string Name
{ get; set; } }

Now when the XML serialization occurs, we get the following XML:

<Person>
    <
PersonName>...PersonName>
Person>

Clean. Simple. Easy. Good enough, right Well, sort of...

What if I wanted to change the way the XML in the following manner

<Person>
    <
FirstName>...FirstName>
    <Surname>...Surname>
Person>

Without directly modifying the type, I`m screwed. The XML serialization attributes don`t provide enough control. Enter the IXmlSerializable interface.

The IXmlSerializable interface is a relatively simple interface:

namespace System.Xml.Serialization
{ public interface IXmlSerializable
{ XmlSchema GetSchema(); void ReadXml(XmlReader reader); void WriteXml(XmlWriter
writer); } }

The two methods we`re most concerned about are ReadXml and WriteXml. These methods will provide you the ability to control the serialization of an object graph into XML and vice versa. GetSchema is a method that is no longer used; rather, the .NET Framework (specifically, the System.Xml.Serialization.XmlSerializer class) leverages an XML schema provider. I`ll explain XML schema providers in just a second. For now, let`s look at an example of what I`m talking about:

public class Person
: IXmlSerializable { string _name; public void XmlSchema
GetSchema() { return null; } public void ReadXml(XmlReader
reader) { while (reader.Read()) { if (reader.NodeType
== XmlNodeType.Element) { if (reader.Name == "FirstName" &&
reader.Read()) _name = (string) reader.Value; if (reader.Name
== "Surname" && reader.Read()) _name += "
" + (string) reader.Value; } } } public void WriteXml(XmlWriter
writer) { writer.WriteElementString("FirstName") writer.WriteElementString("Surname")
} public string Name { get; set; }
}

In this example, I`ve elected to modify the XML that would have been generated. Here`s what the resulting XML looks like:

<Person>
    <
FirstName>...FirstName>
    <Surname>...Surname>
Person>

Pretty nice, eh Now, let`s talk about XML schema providers.

XML schema providers are essentially methods that are delegated for providing the XML Schema representation for a type. These methods are specified by the System.Xml.Serialization.XmlSchemaProviderAttribute attribute. Applying this attribute to the Person class (above) looks like this:

[XmlSchemaProvider("GetPersonSchema") public class Person
: IXmlSerializable { string _name; public static XmlQualifiedName
GetPersonSchema(XmlSchemaSet schemaSet) { XmlSchema schema = new XmlSchema();
schema.TargetNamespace = "http://www.bristowe.com/"; XmlSchemaComplexType
personType = new XmlSchemaComplexType(); personType.Name = "Person";
XmlSchemaSequence sequence = new XmlSchemaSequence(); personType.Particle
= sequence; XmlSchemaElement firstNameElement = new XmlSchemaElement();
firstNameElement.Name = "FirstName"; firstNameElement.SchemaTypeName
= new XmlQualifiedName("string", XmlSchema.Namespace);
sequence.Items.Add(firstNameElement); XmlSchemaElement surnameElement = new XmlSchemaElement();
surnameElement.Name = "Surname"; surnameElement.SchemaTypeName
= new XmlQualifiedName("string", XmlSchema.Namespace);
sequence.Items.Add(surnameElement); schema.Items.Add(personType); schemaSet.Add(schema); return new XmlQualifiedName("Person", "http://www.bristowe.com/");
} public void XmlSchema GetSchema()
{ return null; } public void ReadXml(XmlReader
reader) { while (reader.Read()) { if (reader.NodeType
== XmlNodeType.Element) { if (reader.Name == "FirstName" &&
reader.Read()) _name = (string) reader.Value; if (reader.Name
== "Surname" && reader.Read()) _name += "
" + (string) reader.Value; } } } public void WriteXml(XmlWriter
writer) { writer.WriteElementString("FirstName") } public string Name
{ get; set; } }

So, what does this do Well, when tools like xsd.exe or wsdl.exe request the XML Schema for this type, they first check to see if a XML schema provider has been indicated by the type. If so, the method will be invoked. Otherwise, the schema will be inferred. For the code sample listed above, the following XML Schema is generated:

< complexType name="Person">
    <sequence>
        <element name="FirstName" type="xsd:string" />
        <element name="Surname" type="xsd:string" />
    sequence>
complexType>> >

So, by implementing IXmlSerializable and providing a XML schema provider, you have full control over the XML serialization of your types and their associated schema.>

Here`s my problem: While implementing a XML schema provider, I run into the problem of generating the schema for a type that contains a System.Guid structure. Now, I realize that the Guid is a xsd:string-based restriction simple type defined automatically by the runtime. However, I`m having trouble leveraging this type inside my XML schema provider for my type. That is, the runtime - specifically, the ASP.NET HTTP Runtime - is complaining that it cannot resolve the type, Guid which resides in the namespace "http://microsoft.com/wsdl/types".

I`d love to find a solution to this problem. So far, nothing. Anyone Anyone Bueller


Read comments or post a reply to : A Cry for Help (AKA, Implementing a XML Schema Provider)
Page 17331 of 20224

Newest posts
 

    Email TopXML