Connecting Tech Pros Worldwide Help | Site Map

XML Serialization of complex types as XML attributes

Paulo Morgado [MVP]
Guest
 
Posts: n/a
#1: Jan 23 '06
Hi all

..NET Framework 1.1

I have created several types that are serailized to XML as strings. Someting
like this:

public struct MyInt32 : IXmlSerializable
{
int value;

public MyInt32(int value)
{
this.value = value;
}

public static implicit operator Int32(MyInt32 value)
{
return value.value;
}

public static implicit operator MyInt32(Int32 value)
{
return new MyInt32(value);
}

public static MyInt32 Parse(string str)
{
return int.Parse(str);
}

public static bool TryParse(string str, out MyInt32 value)
{
try
{
value = int.Parse(str);
return true;
}
catch
{
value = 0;
return false;
}
}

XmlSchema IXmlSerializable.GetSchema()
{
return null;
}

void IXmlSerializable.WriteXml(XmlWriter writer)
{
writer.WriteString(XmlConvert.ToString(this.value) );
}

void IXmlSerializable.ReadXml(XmlReader reader)
{
this.value = XmlConvert.ToInt32(reader.ReadString());
}

}

The XML serialization as a XML element works without any problems:

class MyClass
{
[XmlElement("v")]
public MyInt32 myValue;
}

But when I mark myValue with the XmlAttributeAttribute:

class MyClass
{
[XmlAttribute("v")]
public MyInt32 myValue;
}

I get:

System.InvalidOperationException: There was an error reflecting type
'ConsoleApplication.DTO'. ---> System.InvalidOperationException: There was an
error reflecting field 'v'. ---> System.InvalidOperationException: Cannot
serialize member 'v'. XmlAttribute/XmlText cannot be used to encode complex
types.
at
System.Xml.Serialization.XmlReflectionImporter.Imp ortAccessorMapping(MemberMapping
accessor, FieldModel model, XmlAttributes a, String ns, Type
choiceIdentifierType)
at
System.Xml.Serialization.XmlReflectionImporter.Imp ortFieldMapping(StructModel
parent, FieldModel model, XmlAttributes a, String ns)
at
System.Xml.Serialization.XmlReflectionImporter.Imp ortStructLikeMapping(StructModel model, String ns)
--- End of inner exception stack trace ---
at
System.Xml.Serialization.XmlReflectionImporter.Imp ortStructLikeMapping(StructModel model, String ns)
at
System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(TypeModel
model, String ns, ImportContext context, String dataType, Boolean repeats)
--- End of inner exception stack trace ---
at
System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(TypeModel
model, String ns, ImportContext context, String dataType, Boolean repeats)
at System.Xml.Serialization.XmlReflectionImporter.Imp ortElement(TypeModel
model, XmlRootAttribute root, String defaultNamespace)
at System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(Type
type, XmlRootAttribute root, String defaultNamespace)
at System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(Type
type)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String
defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)
at ConsoleApplication.Program.Main()

How can I serialize MyType as a XML attribute?

--
Paulo Morgado

Chris Lovett
Guest
 
Posts: n/a
#2: Jan 24 '06

re: XML Serialization of complex types as XML attributes


The XmlSerializer doesn't know that your IXmlSerializable just calls
WriteString. What if you called WriteElementString instead? So the right
way to do this is expose a string Property

[XmlIgnore]
public MyInt32 MyValue;

[XmlAttribute("v")]
public string myValue {
get { return MyValue.ToString(); }
set { MyValue = MyInt32.Parse(value); }
}



"Paulo Morgado [MVP]" <paulo.morgado@community.nospam> wrote in message
news:69456116-18E6-4F8B-AF03-A8622D88B5A1@microsoft.com...[color=blue]
> Hi all
>
> .NET Framework 1.1
>
> I have created several types that are serailized to XML as strings.
> Someting
> like this:
>
> public struct MyInt32 : IXmlSerializable
> {
> int value;
>
> public MyInt32(int value)
> {
> this.value = value;
> }
>
> public static implicit operator Int32(MyInt32 value)
> {
> return value.value;
> }
>
> public static implicit operator MyInt32(Int32 value)
> {
> return new MyInt32(value);
> }
>
> public static MyInt32 Parse(string str)
> {
> return int.Parse(str);
> }
>
> public static bool TryParse(string str, out MyInt32 value)
> {
> try
> {
> value = int.Parse(str);
> return true;
> }
> catch
> {
> value = 0;
> return false;
> }
> }
>
> XmlSchema IXmlSerializable.GetSchema()
> {
> return null;
> }
>
> void IXmlSerializable.WriteXml(XmlWriter writer)
> {
> writer.WriteString(XmlConvert.ToString(this.value) );
> }
>
> void IXmlSerializable.ReadXml(XmlReader reader)
> {
> this.value = XmlConvert.ToInt32(reader.ReadString());
> }
>
> }
>
> The XML serialization as a XML element works without any problems:
>
> class MyClass
> {
> [XmlElement("v")]
> public MyInt32 myValue;
> }
>
> But when I mark myValue with the XmlAttributeAttribute:
>
> class MyClass
> {
> [XmlAttribute("v")]
> public MyInt32 myValue;
> }
>
> I get:
>
> System.InvalidOperationException: There was an error reflecting type
> 'ConsoleApplication.DTO'. ---> System.InvalidOperationException: There was
> an
> error reflecting field 'v'. ---> System.InvalidOperationException: Cannot
> serialize member 'v'. XmlAttribute/XmlText cannot be used to encode
> complex
> types.
> at
> System.Xml.Serialization.XmlReflectionImporter.Imp ortAccessorMapping(MemberMapping
> accessor, FieldModel model, XmlAttributes a, String ns, Type
> choiceIdentifierType)
> at
> System.Xml.Serialization.XmlReflectionImporter.Imp ortFieldMapping(StructModel
> parent, FieldModel model, XmlAttributes a, String ns)
> at
> System.Xml.Serialization.XmlReflectionImporter.Imp ortStructLikeMapping(StructModel
> model, String ns)
> --- End of inner exception stack trace ---
> at
> System.Xml.Serialization.XmlReflectionImporter.Imp ortStructLikeMapping(StructModel
> model, String ns)
> at
> System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(TypeModel
> model, String ns, ImportContext context, String dataType, Boolean repeats)
> --- End of inner exception stack trace ---
> at
> System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(TypeModel
> model, String ns, ImportContext context, String dataType, Boolean repeats)
> at
> System.Xml.Serialization.XmlReflectionImporter.Imp ortElement(TypeModel
> model, XmlRootAttribute root, String defaultNamespace)
> at System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(Type
> type, XmlRootAttribute root, String defaultNamespace)
> at System.Xml.Serialization.XmlReflectionImporter.Imp ortTypeMapping(Type
> type)
> at System.Xml.Serialization.XmlSerializer..ctor(Type type, String
> defaultNamespace)
> at System.Xml.Serialization.XmlSerializer..ctor(Type type)
> at ConsoleApplication.Program.Main()
>
> How can I serialize MyType as a XML attribute?
>
> --
> Paulo Morgado
>[/color]


Paulo Morgado [MVP]
Guest
 
Posts: n/a
#3: Jan 24 '06

re: XML Serialization of complex types as XML attributes


Hi Chris. Thanks for your reply.

There are two things wrong in your approach to the problem:

1. Parse and ToString, at least in the way you showed, are all about
presentation and are culture dependente. XmlConvert should have been used,
but it's not extensible either.

2. You are not serializing MyValue and you are creating a new property that
I don't want my classes to have. I should have told that I already came to
this conclusion and also added an Obsolete attribute to warn developers not
to use that property.

I can understand that the XmlSerializer doesn't know how i will serialize my
type. There should be a IXmlSerilizableSomething to serialize the type as
just a string and the XmlSerializer should handle it. Another way to do it
would be to let the XmlReader/XmlWriter to handle if proper XML was being
read/written.

--
Paulo Morgado



"Chris Lovett" wrote:
[color=blue]
> The XmlSerializer doesn't know that your IXmlSerializable just calls
> WriteString. What if you called WriteElementString instead? So the right
> way to do this is expose a string Property
>
> [XmlIgnore]
> public MyInt32 MyValue;
>
> [XmlAttribute("v")]
> public string myValue {
> get { return MyValue.ToString(); }
> set { MyValue = MyInt32.Parse(value); }
> }[/color]

Paulo Morgado [MVP]
Guest
 
Posts: n/a
#4: Jan 24 '06

re: XML Serialization of complex types as XML attributes


Hi Chris,

Seems like I dumped my frustration on you. Sorry.

--
Paulo Morgado

Closed Thread