Adam Mańkowski
Adam Mańkowski

Reputation: 948

C# XMLNS complicated deserialization

I'm trying to deserialize XMLNS file.

  <feed xmlns:live="http://www.live.com/marketplace" xmlns="http://www.w3.org/2005/Atom">
  <live:totalItems>1177</live:totalItems>
  <live:numItems>1</live:numItems>
  <title>FindGames Results</title>
  <updated>2013-09-19T09:28:02.77Z</updated>
  <entry live:itemNum="34" live:detailView="3">
    <id>urn:uuid:66ACD000-77FE-1000-9115-D802555308C3</id>
    <updated>2013-09-19T09:28:02.77Z</updated>
    <title>Rayman® Legends</title>
    <content type="text">game content</content>
    <live:media>
      <live:mediaType>1</live:mediaType>
      <live:gameTitleMediaId>urn:uuid:66ACD000-77FE-1000-9115-D802555308C3</live:gameTitleMediaId>
      <live:reducedTitle>Rayman® Legends</live:reducedTitle>
      <live:reducedDescription>The Glade of Dreams is in trouble once again! During a 100-year nap, nightmares have multiplied and spread, creating new monsters even scarier than before!</live:reducedDescription>
      <live:availabilityDate>2013-06-11T00:00:00</live:availabilityDate>
      <live:releaseDate>2013-08-29T00:00:00</live:releaseDate>
      <live:ratingId>20</live:ratingId>
      <live:developer>Ubisoft</live:developer>
      <live:publisher>Ubisoft</live:publisher>
      <live:newestOfferStartDate>2013-09-13T09:00:00Z</live:newestOfferStartDate>
      <live:totalOfferCount>1</live:totalOfferCount>
      <live:titleId>1431505091</live:titleId>
      <live:effectiveTitleId>1431505091</live:effectiveTitleId>
      <live:gameReducedTitle>Rayman® Legends</live:gameReducedTitle>
      <live:ratingAggregate>4.50</live:ratingAggregate>
      <live:numberOfRatings>1193</live:numberOfRatings>
    </live:media>
  </entry>
</feed>

My current code: Deserialize class:

[XmlRoot("feed", Namespace = "http://www.w3.org/2005/Atom")]
public class entry
{
    public string title { get; set; }
    public string totalItems { get; set; }
    public string reducedDescription{ get; set; }
    public string ratingId { get; set; }
    public string developer { get; set; }
    public string publisher { get; set; }
    public string tittleId { get; set; }
    public string ratingAggregate { get; set; }
    public string numberOfRatings { get; set; }
    public string boxImage { get; set; }
    public string categories { get; set; }
}

class deserializeXML
{
    public static void deserialize()
    {
        using (StreamReader reader = new StreamReader("Query.xml"))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(entry));
            entry x1 = serializer.Deserialize(reader) as entry;
        }
    }
}

I just receiving title (FindGames Results instead of Rayman® Legends). I need to get parameters after "entry" and "live:media", i have no idea how to receive parameters with "live:" at the beginning.

EDIT:

[XmlElement(Namespace = "http://www.live.com/marketplace")]
public int numItems { get; set; }
[XmlElement(Namespace = "http://www.live.com/marketplace")]
public int totalItems { get; set; }

It's working well, but:

   [XmlElement("media" Namespace="http://www.live.com/marketplace")]
   public media media{ get; set; }

This returning null media class :/

Upvotes: 2

Views: 612

Answers (1)

dkackman
dkackman

Reputation: 15579

You need to explicitly map those types and properties that are not in the atom namespace to their respective namespaces. The namespace declaration in the XmlRoot just specifies the namespace of the root element. If you have multiple namespaces in the document you need to call them out explicitly.

For instance to map the itemNum attribute correctly try this in your entry class:

[XmlRoot("feed", Namespace = "http://www.w3.org/2005/Atom")]
public class entry
{
    [XmlAttribute("itemNum", Namespace = "http://www.live.com/marketplace")]
    public int itemNum { get; set; }

    public string title { get; set; }
    public string totalItems { get; set; }
    public string reducedDescription { get; set; }
    public string ratingId { get; set; }
    public string developer { get; set; }
    public string publisher { get; set; }
    public string tittleId { get; set; }
    public string ratingAggregate { get; set; }
    public string numberOfRatings { get; set; }
    public string boxImage { get; set; }
    public string categories { get; set; }
}

You then need to declare additional type to map into things like the media node.

class media
{
    public int mediaType{ get; set; }
    public string reducedDescription{ get; set; }
etc. etc.
}

You then need to move all of those "live" properties from your entry class into you new media class leaving you with an entry class that might look like this:

[XmlRoot("feed", Namespace = "http://www.w3.org/2005/Atom")]
    public class entry
    {
        [XmlAttribute("itemNum", Namespace = "http://www.live.com/marketplace")]
        public int itemNum { get; set; }

        public string title { get; set; }

        [XmlElement("media" Namespace="http://www.live.com/marketplace")]
        public media media{ get; set; }
    }

Your class hierarchy does not need to exactly match the xml hierarchy and you can do some significant remapping and transformation of the Xml using the various attributes in System.Xml.Serialization however I find it easier to implement, understand and maintain this sort of stuff if the C# classes map 1:1 onto the xml structure.

Upvotes: 2

Related Questions