2010-01-14 6 views
3

J'ai du code XML que je désérialise en un objet métier. J'utilise XmlSerializer.Deserialize pour le faire. Cependant, je veux que l'un des XmlElement contenus dans le XML reste un XElement.Désérialise partiellement XML en objet

Cela ne peut pas être fait directement (en utilisant un XmlElementAttribute) puisque XElement n'est pas sérialisable. J'ai aussi essayé de sérialisation cet élément à une chaîne (dans un deux étapes tentent d'obtenir un XElement), mais qui a échoué avec l'erreur:

unexpected node type element. readelementstring method can only be called on elements with simple or empty content

Toute idée de comment cela peut être fait?

Voici un exemple de xml et l'objet résultant je veux:

<Person name="Joe"> 
    <Hobbies> 
    <Hobby name="Reading" .../> 
    <Hobby name="Photography" .../> 
    </Hobbies> 
    <HomeAddress> 
    ... 
    </HomeAddress> 
</Person> 

Objet:

public class Person 
    { 
     [XmlAttribute("Name")] 
     public string Name {get; set;} 
     ????? 
     public XElement Hobbies {get; set;} 
     [XmlElement("HomeAddress")] 
     public Address HomeAddress {get; set;} 
    } 

Les tentatives qui ne fonctionnent pas:

[XmlElement("Hobbies")] 
public XElement Hobbies {get; set;} 
[XmlElement("Hobbies")] 
public string Hobbies {get; set;} 

Répondre

3

Pour éviter le dur travail de mettre en œuvre quelque chose comme IXmlSerializable, vous pourriez faire quelque chose dans le sens d'une propriété pass-through XmlElement semi-cachée; Notez, cependant, que cela ne fait pas tout à fait ce que vous voulez, car vous ne pouvez avoir qu'une seule valeur XElement racine (pas deux, selon votre exemple); vous auriez besoin d'une liste pour le faire ...

using System; 
using System.ComponentModel; 
using System.Xml; 
using System.Xml.Linq; 
using System.Xml.Serialization; 
public class Person 
{ 
    [XmlAttribute("Name")] 
    public string Name { get; set; } 
    [XmlIgnore] 
    public XElement Hobbies { get; set; } 

    [XmlElement("Hobbies")] 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
    public XmlElement HobbiesSerialized 
    { 
     get 
     { 
      XElement hobbies = Hobbies; 
      if(hobbies == null) return null; 
      XmlDocument doc = new XmlDocument(); 
      doc.LoadXml(hobbies.ToString()); 
      return doc.DocumentElement; 
     } 
     set 
     { 
      Hobbies = value == null ? null 
       : XElement.Parse(value.OuterXml); 
     } 
    } 
    [XmlElement("HomeAddress")] 
    public Address HomeAddress { get; set; } 
} 

public class Address { } 

static class Progmam 
{ 
    static void Main() 
    { 
     var p = new Person { Hobbies = new XElement("xml", new XAttribute("hi","there")) }; 
     var ser = new XmlSerializer(p.GetType()); 
     ser.Serialize(Console.Out, p); 
    } 
} 
+0

Très agréable. Je ne comprends pas pourquoi il prend le nœud interne lors de la spécification de XmlElementAttribute à 'Loisirs'. J'ai cependant contrôler le XML, donc j'ai simplement ajouté un noeud wrapper autour du nœud 'Hobbies' pour obtenir ce dont j'avais besoin (au lieu d'utiliser une liste). Merci beaucoup. – joerage

1

Pour avoir plein contrôle (avec l'entière responsabilité) de la façon dont le XML est généré, vous pouvez demander à votre classe d'implémenter le System.Xml.S erialization.IXmlSerializable interface, et remplacer ReadXml et WriteXml. J'ai dû le faire avant avec des classes de dictionnaire - assurez-vous de bien tester, en particulier avec des propriétés null, les champs vides, etc.

http://www.devx.com/dotnet/Article/29720

Questions connexes