0

Having some difficulties deserializing the following xml to an object in the most efficient/cleanest possible way:

<item xsi:type="ns2:Map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <item>
        <key xsi:type="xsd:string">mailinglistid</key> 
        <value xsi:type="xsd:string">1</value> 
    </item>
    <item>
        <key xsi:type="xsd:string">uniqueid</key> 
        <value xsi:type="xsd:string">1a0d0d2195</value> 
    </item>
    <item>
        <key xsi:type="xsd:string">name</key> 
        <value xsi:type="xsd:string">OSM NL</value> 
    </item>
</item>

This is a single item along with its properties. As you can see the properties are defined as key/value pairs.

Because they are key value pairs i could not find a way to use the Xml deserialize attributes (as described in this question: How to deserialize xml to object )

Therefore i have created the following alternative:

// Retrieves all the elements from the "return" node in the Mailinglist_allResponse node.
var items = response.ResponseFromServer.Descendants(_engineResponseNamespace + "Mailinglist_allResponse").Descendants("return").Elements();

foreach (var item in items)
{
    var values = item.Descendants("item").ToArray();

    var list = new EngineMailingList
    {
        MailingListId =
            values.Descendants("key")
                .First(v => v.Value == "mailinglistid")
                .ElementsAfterSelf("value")
                .First()
                .Value,
        UniqueId =
            values.Descendants("key")
                .First(v => v.Value == "uniqueid")
                .ElementsAfterSelf("value")
                .First()
                .Value,
        Name =
            values.Descendants("key")
                .First(v => v.Value == "name")
                .ElementsAfterSelf("value")
                .First()
                .Value,
    };

    result.Add(list);

As you can see this is alot more code than when using the deserialize attributes. Is there any way i could still use these attributes so that my code could be cleaner/ efficient? i am going to have to make alot of these functions otherwise.

Community
  • 1
  • 1
Jurgen Welschen
  • 871
  • 1
  • 13
  • 21
  • That XML looks invalid. There should be namespaces corresponding to the namespace prefixes `ns` and `xsd` from `xsi:type="ns2:Map"` and `xsi:type="xsd:string"`. That [`xsi:type`](https://www.w3.org/TR/xmlschema-1/#xsi_type) attribute is a standard way to specify the type of a polymorphic element, see [Xsi:type Attribute Binding Support](https://msdn.microsoft.com/en-us/library/ca1ks327.aspx). – dbc Apr 01 '16 at 16:10
  • Sorry, the xml in the post is just a part of it. It has the namespaces in the top, i just decided not to include them in this post. – Jurgen Welschen Apr 01 '16 at 18:33
  • @Jurgen Welschen can you show us the namespaces that you didn't include.... – Monty Apr 01 '16 at 20:28

1 Answers1

1

I don't think attributes will work because of key/value structure. There is no way for a program to infer from the xml alone what properties an object has. I would make a static extension method helper function to get the values:

public static string GetValue(this XElement element, string key){
       return values.Descendants("key")
                    .First(v => v.Value == key)
                    .ElementsAfterSelf("value")
                    .First()
                    .Value;
    }

That way your code could look like this:

MailingListId = values.GetValue("mailinglistid"),
UniqueId = values.GetValue("uniqueid"),
Name = values.GetValue("name")
jle
  • 9,316
  • 5
  • 48
  • 67
  • Ok thanks! so no real way to do this with deserialization attributes. The helper function is a good idea! – Jurgen Welschen Apr 01 '16 at 18:35
  • You might be able to make your own custom attribute for this, but might be more trouble than it is worth – jle Apr 01 '16 at 18:37