Wesley Smith
Wesley Smith

Reputation: 19571

Deserialize XML node nested in itself

I have xml from a soap response that looks like the below (which I dont control the format of), note the nested Campaigns.Campaign.Campaign

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
   <s:Header>
      // ...
   </s:Header>
   <s:Body>
      <SomeResponse xmlns="...">
         <SomeCampaignsResult xmlns:b="..." xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <b:Campaigns>
               <b:Campaign>
                  <b:Campaign>
                     <b:CampaignId>dfdf-dfe-fdf</b:CampaignId>
                     <b:CampaignName>Some name</b:CampaignName>
                  </b:Campaign>
               </b:Campaign>
               <b:CampaignCount>1</b:CampaignCount>
            </b:Campaigns>
         </SomeCampaignsResult>
      </SomeResponse>
   </s:Body>
</s:Envelope>

I have the following classes:

namespace Models
{
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "...")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "...", IsNullable = false)]
    public class Campaigns
    {
        public int CampaignCount { get; set; }
        public Campaign Campaign { get; set; }
    }
}


namespace Models
{
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "...")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "...", IsNullable = false)]
    public class Campaign
    {
        public string CampaignId { get; set; }
        public string Name { get; set; }
    }
}

Im trying to deserialize the given xml with this code

    XmlDocument SOAPResponse = new XmlDocument();
    SOAPResponse.Load("C:\\campaign.xml");

    XmlNamespaceManager nsmgr = new XmlNamespaceManager(SOAPResponse.NameTable);
    nsmgr.AddNamespace("s", "http://www.w3.org/2003/05/soap-envelope");
    nsmgr.AddNamespace("a", "http://www.w3.org/2005/08/addressing");
    nsmgr.AddNamespace("b", "...");
    nsmgr.AddNamespace("i", "http://www.w3.org/2001/XMLSchema-instance");

    XmlNode justNodes1 = SOAPResponse.SelectSingleNode("//s:Envelope/s:Body", nsmgr);
    XmlNode nodeCampaigns = justNodes1.SelectSingleNode(".//b:Campaigns", nsmgr);
    Campaigns responseCampaigns = null;
    XmlSerializer serializerCampaigns = new XmlSerializer(typeof(Campaigns));
    using (XmlReader reader = new XmlNodeReader(nodeCampaigns))
    {
       responseCampaigns = (Campaigns)serializerCampaigns.Deserialize(reader);
    }

And this is the value of responseCampaigns at the end:

enter image description here

Problem

responseCampaigns.CampaignCount is correctly parsed/set responseCampaigns.Campaign.CampaignId and responseCampaigns.Campaign.Nameare both null since I am not properly accounting for the Campaigns.Campaign.Campaign nesting

How can I change my model structure to properly account for the Campaigns.Campaign.Campaign nesting?

Upvotes: 1

Views: 77

Answers (2)

Wesley Smith
Wesley Smith

Reputation: 19571

Changing my Campaigns model to specify XmlArrayItem and XmlArray both with the ElementName Campaign and changing the Campaign member to a List solved this problem for me.

namespace Models
{
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "...")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "...", IsNullable = false)]
    public class Campaigns
    {
        public int CampaignCount { get; set; }

        [XmlArrayItem(ElementName = "Campaign")]
        [XmlArray(ElementName = "Campaign")]
        public List<Campaign>  Campaign { get; set; }
    }
}

Upvotes: 1

jdweng
jdweng

Reputation: 34421

You have two different namespace "..."which is giving an issue. Try code below :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication183
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
            Envelope envelope = (Envelope)serializer.Deserialize(reader);

        }
    }
    [XmlRoot(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
    public class Envelope
    {
        [XmlElement(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
        public Body Body { get; set; }
    }
    public class Body
    {
        [XmlArray(ElementName = "SomeResponse", Namespace = "empty")]
        [XmlArrayItem(ElementName = "SomeCampaignsResult", Namespace = "empty")]
        public List<CampaignsResult> CampaignsResult { get; set; }
    }
    public class CampaignsResult
    {
        [XmlArray(ElementName = "Campaigns", Namespace = "bspace")]
        [XmlArrayItem(ElementName = "Campaign", Namespace = "bspace")]
        public List<Campaigns> Campaigns { get; set; }
    }
    public class Campaigns
    {
        [XmlElement(Namespace = "bspace")]
        public Campaign Campaign { get; set; }
    }
    public class Campaign
    {
        public string CampaignId { get;set;}
        public string CampaignName { get; set; }
    }

 
}

Upvotes: 1

Related Questions