2010-01-14 4 views
3

У меня есть XML, который я десериализую в бизнес-объект. Я использую XmlSerializer.Deserialize для этого. Однако я хочу, чтобы один из XmlElement, содержащийся в XML, оставался XElement.Частично десериализовать XML для объекта

Это невозможно сделать напрямую (с использованием XmlElementAttribute), поскольку XElement не является Serializable. Я также попытался сериализовать этот элемент в строку (в два шага пытаются получить XElement), но потерпела неудачу с ошибкой:

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

Любая идея, как это может быть сделано?

Вот пример XML и полученный объект, который я хочу:

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

Объект:

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

попытки, которые не работают:

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

ответ

3

Чтобы избежать тяжелой работы реализации что-то вроде IXmlSerializable, вы могли бы сделать что-то по линии полускрытого pass-thru XmlElement; обратите внимание, однако, что это не совсем делает то, что вы хотите, поскольку у вас может быть только один корень XElement значение (не два, как в вашем примере); вам понадобится список для этого ...

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

Очень приятно. Я не понимаю, почему он занимает внутренний узел при указании XmlElementAttribute в «Хобби». Однако я контролирую XML, поэтому я просто добавил узел обертки вокруг узла «Хобби», чтобы получить то, что мне нужно (вместо использования списка). Большое спасибо. – joerage

1

Чтобы иметь полный (наряду с полной ответственностью) за то, как генерируется XML, вы можете реализовать свой класс System.Xml.S erialization.IXmlSerializable, и переопределяет ReadXml и WriteXml. Я должен был сделать это раньше с классами словаря - не забудьте тщательно проверить, особенно с нулевыми свойствами, пустые поля и т.д.

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

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