0

I'm using the built in XML deserialization (not because it was my choice, but legacy code) to deserialize xml to a strong typed object.

NOTE: I have no control over the xml, it is an external api

The problem is an xml node has been extended to include a child node of the same name and it's breaking the serialization.

For example, the xml as follows:

<people>
  <person>
    <id>1234</id>
    <person>
      <name>This is my name</name>
    <person>
   </person>
</people>

With the following objects

[XmlType("person")]
public class Person {

  [XmlElement("id")]
  public int Id { get; set; }

  [XmlElement("person")]
  public PersonTitle Title{ get; set; }
}

[XmlType("person")]
pulic class PersonTitle
{
   [XmlElement("name")]
   public string Name { get; set; }
}

This is throwing an error when calling (T)xmlserializer.Deserialize(stream) due to the duplicate names even though the xml is valid. Personally I would not have gone to the trouble to replicate the xml layout in objects just to automatically deserialize it when manually deserializing is easier to maintain (especially when it's never serialized by .net in the first place).

However, I'd like to know if there's a way I can get around this even if it means flattenting the child object out.

I know this doesn't work, but as example:

[XmlType("person")]
public class Person {

  [XmlElement("id")]
  public int Id { get; set; }

  [XmlElement("person/name")]
  public string Title{ get; set; }
}

Any help is appreciated.

Gats
  • 3,452
  • 19
  • 20

2 Answers2

2

The easiest method might be to run it through an XSLT transform before deserializing it- match the person/person/name elements and output just the person/name part. Then deserialize the result.

Here's a SO post on applying XSLT within C#: How to apply an XSLT Stylesheet in C#

And here is one on using XSLT to replace elements: http://cvalcarcel.wordpress.com/2008/09/06/replacing-arbitrary-xml-located-within-an-xml-document-using-xslt/

Community
  • 1
  • 1
Chris Shain
  • 50,833
  • 6
  • 93
  • 125
  • Ok, so there really isn't a way to step around the deserializer insisting that child elements be named uniquely to their parent? – Gats May 04 '11 at 03:43
  • 1
    It may be possible, though I doubt it, to add a Name property and an appropriately-attributed NestedPerson property to the person class, and make all of the properties semantically optional. That MIGHT trick the XmlSerializer into creating an outer person instance with all of the other properties, and another person instance in it's NestedPerson property with only the name attribute set. But that seems like way more of a hack than an XSLT pre-processor. – Chris Shain May 04 '11 at 03:53
  • Thanks for the input. I'll leave it a bit longer as my real world situation has a full library of objects where the deserialization is totally run by the annotations. I would have a lot to re-test if I meddle too much with the actual service call. Again, I wouldn't have done it this way myself, but I'm stuck with it for now. If I don't get any quicker fixes, I'll mark as answer... thanks again! – Gats May 04 '11 at 03:59
0

In a worst case scenario you could write the class however you like (don't compromise due to serialization) and then implement IXmlSerializable. Implement ReadXml, throw NotImplementedException for WriteXml if you like.

Craig Celeste
  • 12,207
  • 10
  • 42
  • 49
  • It is written to match the xml being sent to us. The problem is the XmlSerializer doesn't like the fact that the parent element and the child element share the same XmlElement of "person". Just wondering if there's a work around that would be quicker than rewriting the parsing that's there. It is for a very complex rest interface and would be days of work to rewrite. – Gats May 04 '11 at 03:25