Deserializing duplicate XML elements with unique attributes

走远了吗. 提交于 2019-12-24 00:12:25

问题


I have the following XML structure:

<Response>
  <Value Name="ID">1</Value>
  <Value Name="User">JSmith</Value>
  <Value Name="Description">Testing 123</Value>
</Response>

How can I deserialize this so that the value names are properties on the class, and the text values are the values of the properties?

Note that the value names never change, so Name="ID" will always exist, for example.

Here is my class so far:

[Serializable]
[XmlRoot("Response")]
public class ReportingResponse
{
    // [What goes here?]
    public string ID { get; set; }

    // [...]
    public string User { get; set; }

    // [...]
    public string Description { get; set; }
}

回答1:


That XML is structured as a collection of name/value pairs rather than as a class with predefined properties, and it would be easier and more natural to deserialize it as such.

If you're determined to deserialize into a class, assuming you're using XmlSerializer, you could introduce a proxy array of name/value pairs for that purpose, like so:

public class NameValuePair
{
    [XmlAttribute]
    public string Name { get; set; }

    [XmlText]
    public string Value { get; set; }

    public override string ToString()
    {
        return string.Format("Name={0}, Value=\"{1}\"", Name, Value);
    }
}

[Serializable]
[XmlRoot("Response")]
public class ReportingResponse
{
    [XmlElement(ElementName="Value")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public NameValuePair[] XmlNameValuePairs
    {
        get
        {
            return NameValuePairExtensions.GetNamedValues(this).ToArray();
        }
        set
        {
            NameValuePairExtensions.SetNamedValues(this, value);
        }
    }

    [XmlIgnore]
    public string ID { get; set; }

    [XmlIgnore]
    public string User { get; set; }

    [XmlIgnore]
    public string Description { get; set; }
}

And then some reflection to automatically load up the array:

public static class NameValuePairExtensions
{
    public static List<NameValuePair> GetNamedValues<T>(T obj)
    {
        if (obj == null)
            throw new ArgumentNullException();
        var type = obj.GetType();
        var properties = type.GetProperties();
        List<NameValuePair> list = new List<NameValuePair>();
        foreach (var prop in properties)
        {
            if (prop.PropertyType == typeof(string))
            {
                var getter = prop.GetGetMethod();
                var setter = prop.GetSetMethod();

                if (getter != null && setter != null) // Confirm this property has public getters & setters.
                {
                    list.Add(new NameValuePair() { Name = prop.Name, Value = (string)getter.Invoke(obj, null) });
                }
            }
        }
        return list;
    }

    public static void SetNamedValues<T>(T obj, IEnumerable<NameValuePair> values)
    {
        if (obj == null || values == null)
            throw new ArgumentNullException();
        var type = obj.GetType();
        foreach (var value in values)
        {
            var prop = type.GetProperty(value.Name);
            if (prop == null)
            {
                Debug.WriteLine(string.Format("No public property found for {0}", value));
                continue;
            }
            try
            {
                prop.SetValue(obj, value.Value, null);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception setting " + value.ToString() + " : \n" + ex.ToString());
            }
        }
    }
}

This fills the array with all string-valued property names and values. You might want something more intelligent, in which case manually filling the array, labeling properties with a custom attribute indicating those to be exported, or whatever, might be more appropriate.



来源:https://stackoverflow.com/questions/26960542/deserializing-duplicate-xml-elements-with-unique-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!