21

I want to create a custom XML structure as follows:

<Hotels>
    <Hotel />
</Hotels>

I've created an implementation of List just to be able to do this. My code is as follows:

[XmlRootAttribute(ElementName="Hotels")]
public class HotelList: List<HotelBasic>

Because the class that List holds is not named Hotel but HotelBasic my xml is like

<Hotels>
   <HotelBasic />
</Hotels>

How do I fix this without having to implement ISerializable or IEnumerable?

1
  • Do you want serialize or deserialize? Commented Nov 24, 2011 at 9:07

3 Answers 3

36
[XmlArray("Hotels")]
[XmlArrayItem(typeof(Hotel), ElementName="Hotel")]
public HotelList[] Messages { get; set; }

should produce:

<Hotels>
    <Hotel />
    <Hotel />
</Hotels>

[XmlRoot("Hotels")]
public class HotelList : IXmlSerializable
{
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        this.Hotels = XDocument.Load(reader)
                               .Select(h => new Hotel { Name = (string)h.Attribute("name") }
                               .ToList();
    }

    public void WriteXml(XmlWriter writer)
    {
        throw new NotSupportedException();
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

I need to use List<HotelBasic>, not HotelBasic[]
@odyodyodys: 1. XmlSerializer supports only array. 2. You asked for IEnumerable<T>, array implements it. 3. You do not want List<T> because it's a expendable container, but list in xml is final. 4. You can create list calling ToList().
I am using Lists methods like Find and lots more. It would be just pain to reimplement List
@odyodyodys: You can call ToList().Find(...), or use not XmlSerializer and set of attributes, but mark only root element and implement IXmlSerializable for custom structure.
@odyodyodys: I've updated my answer how to implement IXmlSerializable.
|
21

Assuming you are using XmlSerializer, if all you want to do is change how your HotelBasic class is serialized, you can use XmlTypeAttribute:

[XmlType(TypeName = "Hotel")]
public class HotelBasic
{
    public string Name { get; set; }
}

When used with your HotelList class it will be serialized as:

<Hotels xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Hotel>
    <Name>One</Name>
  </Hotel>
  <Hotel>
    <Name>Two</Name>
  </Hotel>
</Hotels>

Comments

8

I think madd0 shows the simplest option for you here, but just for completeness... personally I don't recommend the "serialize the list as the root object" - for various reasons (including: I've seen those attributes not work on at least on platform - might have been CF or SL, can't remember). Instead, I always advise using a custom root type:

[XmlRoot("Hotels")]
public class HotelResult // or something similar
{
    [XmlElement("Hotel")]
    public List<HotelBasic> Hotels { get { return hotel; } }

    private readonly List<HotelBasic> hotels = new List<HotelBasic>();
}

This will have the same xml structure, and allows greater flexibility (you can add other attributes / elements to the root), and doesn't bake List<T> into your type model (prefer encapsulation over inheritance, etc).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.