S.Ponsford
S.Ponsford

Reputation: 43

How to deserialize element with list of attributes in C#

Hi I have the following Xml to deserialize:

<RootNode>
    <Item
      Name="Bill"
      Age="34"
      Job="Lorry Driver"
      Married="Yes" />
    <Item
      FavouriteColour="Blue"
      Age="12"
    <Item
      Job="Librarian"
       />
    </RootNote>

How can I deserialize the Item element with a list of attribute key value pairs when I dont know the key names or how many attributes there will be?

Upvotes: 1

Views: 2691

Answers (2)

dbc
dbc

Reputation: 116534

You can use the XmlAnyAttribute attribute to specify that arbitrary attributes will be serialized and deserialized into an XmlAttribute [] property or field when using XmlSerializer.

For instance, if you want to represent your attributes as a Dictionary<string, string>, you could define your Item and RootNode classes as follows, using a proxy XmlAttribute[] property to convert the dictionary from and to the required XmlAttribute array:

public class Item
{
    [XmlIgnore]
    public Dictionary<string, string> Attributes { get; set; }

    [XmlAnyAttribute]
    public XmlAttribute[] XmlAttributes
    {
        get
        {
            if (Attributes == null)
                return null;
            var doc = new XmlDocument();
            return Attributes.Select(p => { var a = doc.CreateAttribute(p.Key); a.Value = p.Value; return a; }).ToArray();
        }
        set
        {
            if (value == null)
                Attributes = null;
            else
                Attributes = value.ToDictionary(a => a.Name, a => a.Value);
        }
    }
}

public class RootNode
{
    [XmlElement("Item")]
    public List<Item> Items { get; set; }
}

Prototype fiddle.

Upvotes: 1

schroeder
schroeder

Reputation: 153

Using XmlDocument class you can just select the "Item" nodes and iterate through the attributes:

string myXml = "<RootNode><Item Name=\"Bill\" Age=\"34\" Job=\"Lorry Driver\" Married=\"Yes\" /><Item FavouriteColour=\"Blue\" Age=\"12\" /><Item Job=\"Librarian\" /></RootNode>"
XmlDocument doc = new XmlDocument();
doc.LoadXml(myXml);
XmlNodeList itemNodes = doc.SelectNodes("RootNode/Item");
foreach(XmlNode node in itemNodes)
{
    XmlAttributeCollection attributes = node.Attributes;
    foreach(XmlAttribute attr in attributes)
    {
         // Do something...
    }
}

Or, if you want an object containing only the Attributes as List of KeyValuePairs, you could use something like:

var items = from XmlNode node in itemNodes
            select new 
            {
                Attributes = (from XmlAttribute attr in node.Attributes
                              select new KeyValuePair<string, string>(attr.Name, attr.Value)).ToList()
            };

Upvotes: 0

Related Questions