2014-11-16 2 views
2

я иметь следующую структуру XML:десериализация дубликата элементы XML с уникальными атрибутами

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

Как десериализации это так, чтобы имена таких значений свойств на классе, и текстовые значения являются значениями свойств ?

Обратите внимание, что имена значений никогда не меняются, поэтому Name="ID" будет всегда существовать, например.

Вот мой класс до сих пор:

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

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

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

Я предполагаю, что вы используете ['XmlSerializer'] (http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer%28v=vs.110%29.aspx). Это верно? – dbc

+0

@ dbc Да, это правильно. – qJake

ответ

3

Это XML структурированы в виде набора пар имя/значение, а не как класс с заданными свойствами, и это было бы проще и естественнее десериализации его как таковой.

Если вы решили десериализации в классе, при условии, что вы используете XmlSerializer, вы можете ввести прокси-массив пар имя/значение для этой цели, например, так:

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; } 
} 

, а затем некоторые отражение для автоматической загрузки массива:

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()); 
      } 
     } 
    } 
} 

Это заполняет массив всеми именами и значениями значений значений. Возможно, вам понадобится что-то более интеллектуальное, и в этом случае вручную заполнить массив, может быть более подходящим для маркировки свойств с помощью настраиваемого атрибута, указывающего экспортируемые или что-то еще.

+0

Это то, что я понял. Благодарю. Однако это работает, я думаю, что более простой способ (по крайней мере, для моей реализации) состоит в том, чтобы просто создать класс «Значение», сохранить результаты в массиве, а затем использовать Getter ссылки на свойство в массиве с использованием Linq (например, 'public string ID {get {return myValues.FirstOrDefault (v => v.Name ==" ID ");}}'). – qJake

+0

[XmlText] был ключом к решению моей проблемы. Это то, что позволяет поместить значение в элемент без того, чтобы это имя переменной стало новым элементом. – redwards510

Смежные вопросы