user1086419
user1086419

Reputation: 85

XmlDeserialize conditional Deserialization based on Attribute Value

I am trying to Deserialize the following XML:

<Test><string name="Name">Test name</string><string name="Description">Some fake description.</string></Test>

Into the following class.

[XmlRoot("Test")]
public class Test
{
 [XmlElement("string")]
 public string Name;

 [XmlElement("string")]
 public string Description;
}

Using the code I am doing it with.

var xml = @"<Test><string name=""Name"">Test name</string><string name=""Description"">Some fake description.</string></Test>";
XmlReader reader = new XmlTextReader(new StringReader(xml));
XmlSerializer serializer = new XmlSerializer(typeof(Test));
serializer.Deserialize(reader);

When I run this I get an InvalidOperationException with the message

There was an error reflecting type 'Test'.

If I comment out the Description property, it works. I can get the attribute value or the text, but I can't get just the XmlText with the element is string and the "name" Attribute has a specific value.

Is this even possible without using LINQ?

Upvotes: 2

Views: 1592

Answers (3)

yamen
yamen

Reputation: 15618

As per my comment:

Certainly won't be able to do it without changing something. You're telling .NET that Description is an element when it's an attribute of the 'string' element. Use LINQ

Here is an example of the LINQ, it's quite straightforward to extend and decouples your XML from your class (which is often a good thing!).

var xml = @"<Test><string name=""Name"">Test name</string><string name=""Description"">Some fake description.</string></Test>";
var xdoc = XDocument.Parse(xml);

var output = from test in xdoc.Elements("Test")
             let strings = test.Elements("string").ToDictionary(e => e.Attribute("name").Value, e => e.Value)
             select new Test () { Name = strings["Name"],
                                  Description = strings["Description"] };

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1062865

For that you would need:

public class Foo {
    [XmlAttribute("name")]
    public string Name {get;set;}
    [XmlText]
    public string Value {get;set;}
}

Then, in the parent type:

[XmlRoot("Test")]
public class Test
{
    [XmlElement("string")]
    public List<Foo> Items {get;set;}
}

This it the only way you can process that shape XML unless you use IXmlSerializable (very hard).

Upvotes: 0

user694833
user694833

Reputation:

The reason is that you are not using XmlElement as intended, the element name "string" must be unique the class. The "name" attribute is not taken into account.

So, in summary, it is not possible to deserialize that xml document automatically, you would need to implement the deserialization method by yourself.

Upvotes: 0

Related Questions