Get a reference to the parent object when deserializing XML in C#

March 16, 2009

This is the code I used in response to an answer to a question I posted on stackoverflow.

Briefly, I was wondering how to hold a reference to the parent object in one of it’s children when deserializing the following hierarchical XML: –

<report xmlns="http://schemas.stuartwhiteford.com/">
    <id>1</id>
    <dateCreated>2009-03-16</dateCreated>
    <title>Report Title</title>
    <subTitle>Report SubTitle</subTitle>
    <sections>
        <section>
            <id>2</id>
            <title>Section</title>
        </section>
    </sections>
</report>

The answer was to use the DataContractSerializer, which is used to serialize and deserialize data sent in Windows Communication Foundation (WCF) messages. For this to work though, we need to modify our XML slightly to include references between the parent and child elements: –

<report z:Id="1" xmlns="http://schemas.stuartwhiteford.com/" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
    <id>1</id>
    <dateCreated>2009-03-16</dateCreated>
    <title>Report Title</title>
    <subTitle>Report SubTitle</subTitle>
    <sections>
        <section z:Id="2">
            <report z:Ref="1" xsi:nil="true"/>
            <id>4</id>
            <title>Section</title>
        </section>
    </sections>
</report>

Here’s the code required to deserialize: –

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
 
namespace ReportSample
{
 
    [DataContract(Name = "report", Namespace = "http://schemas.stuartwhiteford.com/")]
    public class Report
    {
 
        private int _id;
        private DateTime _dateCreated;
        private string _title;
        private string _subTitle;
        private Sections _sections;
 
        [DataMember(Name = "id", Order = 1)]
        public int ID
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
            }
        }
 
        [DataMember(Name = "dateCreated", Order = 2)]
        public DateTime DateCreated
        {
            get
            {
                return _dateCreated;
            }
            set
            {
                _dateCreated = value;
            }
        }
 
        [DataMember(Name = "title", Order = 3)]
        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                _title = value;
            }
        }
 
        [DataMember(Name = "subTitle", Order = 4)]
        public string SubTitle
        {
            get
            {
                return _subTitle;
            }
            set
            {
                _subTitle = value;
            }
        }
 
        [DataMember(Name = "sections", Order = 5)]
        public Sections Sections
        {
            get
            {
                return _sections;
            }
            set
            {
                _sections = value;
            }
        }
 
    }
 
    [DataContract(Name = "section", Namespace = "http://schemas.stuartwhiteford.com/")]
    public class Section
    {
 
        private Report _report;
        private int _id;
        private string _title;
 
        [DataMember(Name = "report", Order = 1)]
        public Report Report
        {
            get
            {
                return _report;
            }
            set
            {
                _report = value;
            }
        }
 
        [DataMember(Name = "id", Order = 2)]
        public int ID
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
            }
        }
 
        [DataMember(Name = "title", Order = 3)]
        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                _title = value;
            }
        }
 
        public string Key
        {
            get
            {
                return _id.ToString();
            }
        }
 
    }
 
    public class Sections : KeyedCollection<string, Section>
    {
 
        protected override string GetKeyForItem(Section item)
        {
            return item.Key;
        }
 
    }
 
    class Program
    {
 
        static void Main(string[] args)
        {
            try
            {
                DataContractSerializer dcs = new DataContractSerializer(typeof(Report), null, int.MaxValue, false, true, null);
                FileStream fs = new FileStream(@"C:\OfficeReportsReportSample.xml", FileMode.Open);
                XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
                Report r = (Report)dcs.ReadObject(reader, true);
                reader.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadLine();
            }
        }
 
    }
 
}

References


Profile picture

Written by Stuart Whiteford
A software developer with over 20 years' experience developing business applications primarily using Microsoft technologies including ASP.NET (Web Forms, MVC and Core), SQL Server and Azure.