questions/48652270/how-to-deserialize-a-node-in-a-large-document-using-xmlserializer

CSharp · Console

/Program.cs

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Data;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO.Compression;

    //https://stackoverflow.com/questions/48652270/how-to-deserialize-a-node-in-a-large-document-using-xmlserializer
	/// <remarks/>
	[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
	[System.SerializableAttribute()]
	[System.Diagnostics.DebuggerStepThroughAttribute()]
	[System.ComponentModel.DesignerCategoryAttribute("code")]
	[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://MyNamespace")]
	[System.Xml.Serialization.XmlRootAttribute(Namespace="http://MyNamespace", IsNullable=false)]
	public partial class RootNode {
	
		private Car[] carsField;
	
		/// <remarks/>
		[System.Xml.Serialization.XmlArrayItemAttribute(IsNullable=false)]
		public Car[] Cars {
			get {
				return this.carsField;
			}
			set {
				this.carsField = value;
			}
		}
	}
	
	/// <remarks/>
	[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
	[System.SerializableAttribute()]
	[System.Diagnostics.DebuggerStepThroughAttribute()]
	[System.ComponentModel.DesignerCategoryAttribute("code")]
	[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://MyNamespace")]
	public partial class Car {
	
		private string makeField;
	
		/// <remarks/>
		[System.Xml.Serialization.XmlAttributeAttribute()]
		public string make {
			get {
				return this.makeField;
			}
			set {
				this.makeField = value;
			}
		}
	}

    class TestClass
    {
        public static void Test()
        {
            TestMcve();
        }

        static string XmlContent = @"
    <RootNode xmlns=""http://MyNamespace"">
        <Cars>
        <Car make=""Volkswagen"" />
        <Car make=""Ford"" />
        <Car make=""Opel"" />
        </Cars>
    </RootNode>";

        static void TestMcve()
        {
            var doc = new XmlDocument();
            doc.LoadXml(XmlContent);
            var nsMgr = new XmlNamespaceManager(doc.NameTable);
            nsMgr.AddNamespace("myns", "http://MyNamespace");
            var rootSerializer = new XmlSerializer(typeof(RootNode));
            var root = (RootNode)rootSerializer.Deserialize(new XmlNodeReader(doc));
            Console.WriteLine(root.Cars[0].make); // Works fine so far

            var node = doc.DocumentElement.SelectSingleNode("myns:Cars", nsMgr);
            Console.WriteLine(node.OuterXml);

            var nodes = doc.DocumentElement.SelectNodes("myns:Cars/myns:Car", nsMgr);
            var cars = nodes.DeserializeList<Car>();

			Console.WriteLine("\nResult of deserializing the {0} node", node.Name);
            Console.WriteLine(cars.GetXml());
        }
    }

    public static partial class XmlNodeExtensions
    {
        public static List<T> DeserializeList<T>(this XmlNodeList nodes)
        {
            return nodes.Cast<XmlNode>().Select(n => n.Deserialize<T>()).ToList();
        }

        public static T Deserialize<T>(this XmlNode node)
        {
            if (node == null)
                return default(T);
            var serializer = XmlSerializerFactory.Create(typeof(T), node.LocalName, node.NamespaceURI);
            using (var reader = new XmlNodeReader(node))
            {
                return (T)serializer.Deserialize(reader);
            }
        }
    }

    public static class XmlSerializerFactory
    {
        // To avoid a memory leak the serializer must be cached.
        // https://stackoverflow.com/questions/23897145/memory-leak-using-streamreader-and-xmlserializer
        // This factory taken from 
        // https://stackoverflow.com/questions/34128757/wrap-properties-with-cdata-section-xml-serialization-c-sharp/34138648#34138648

        readonly static Dictionary<Tuple<Type, string, string>, XmlSerializer> cache;
        readonly static object padlock;

        static XmlSerializerFactory()
        {
            padlock = new object();
            cache = new Dictionary<Tuple<Type, string, string>, XmlSerializer>();
        }

        public static XmlSerializer Create(Type serializedType, string rootName, string rootNamespace)
        {
            if (serializedType == null)
                throw new ArgumentNullException();
            if (rootName == null && rootNamespace == null)
                return new XmlSerializer(serializedType);
            lock (padlock)
            {
                XmlSerializer serializer;
                var key = Tuple.Create(serializedType, rootName, rootNamespace);
                if (!cache.TryGetValue(key, out serializer))
                    cache[key] = serializer = new XmlSerializer(serializedType, new XmlRootAttribute { ElementName = rootName, Namespace = rootNamespace });
                return serializer;
            }
        }
    }

    public static class XmlSerializationHelper
    {
        public static T LoadFromXml<T>(this string xmlString, XmlSerializer serial = null)
        {
            serial = serial ?? new XmlSerializer(typeof(T));
            using (var reader = new StringReader(xmlString))
            {
				return (T)serial.Deserialize(reader);
            }
        }

        public static string GetXml<T>(this T obj, bool omitStandardNamespaces)
        {
			return obj.GetXml(null, omitStandardNamespaces);
        }
		
        public static string GetXml<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = false)
        {
            XmlSerializerNamespaces ns = null;
            if (omitStandardNamespaces)
            {
                ns = new XmlSerializerNamespaces();
                ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
            }			
            using (var textWriter = new StringWriter())
            {
                var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes.
                using (var xmlWriter = XmlWriter.Create(textWriter, settings))
                    (serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns);
                return textWriter.ToString();
            }
        }

    }
				
    public class AssertionFailedException : System.Exception
    {
        public AssertionFailedException() : base() { }

        public AssertionFailedException(string s) : base(s) { }
    }

    public static class Assert
    {
        public static void IsTrue(bool value)
        {
            IsTrue(value, "failed");
        }

        public static void IsTrue(bool value, string message)
        {
            if (value == false)
                throw new AssertionFailedException(message ?? "failed");
        }
    }
						
	public class Program
	{
		public static void Main()
		{
			Console.WriteLine("Roslyn 2.0 Compiler; Environment version: " + Environment.Version);
			Console.WriteLine();

			try
			{
				TestClass.Test();
			}
			catch (Exception ex)
			{
				Console.WriteLine("Uncaught exception: ");
				Console.WriteLine(ex);
				throw;
			}
		}
	}
;