using System.Collections.Generic;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Globalization;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using System.Runtime.InteropServices;
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Truck))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Car))]
public partial class Vehicle
public string Manufacturer { get; set; }
public partial class Truck : Vehicle
public int Load { get; set; }
public partial class Car : Vehicle
public string Configuration { get; set; }
public partial class Garage
Vehicles = new List<Vehicle>();
public List<Vehicle> Vehicles { get; set; }
static string GetOriginalXml()
var xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<Manufacturer>Honda</Manufacturer>
<Configuration>Sedan</Configuration>
<Manufacturer>Volvo</Manufacturer>
static string GetFixedXml()
var xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Garage xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<Vehicles xsi:type=""Car"">
<Manufacturer>Honda</Manufacturer>
<Configuration>Sedan</Configuration>
<Vehicles xsi:type=""Truck"">
<Manufacturer>Volvo</Manufacturer>
static string GetFixedXmlWithWrapperElement()
var xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Garage xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<Vehicle xsi:type=""Car"">
<Manufacturer>Honda</Manufacturer>
<Configuration>Sedan</Configuration>
<Vehicle xsi:type=""Truck"">
<Manufacturer>Volvo</Manufacturer>
internal static void Test()
Console.WriteLine("Validating original XML with original XSD: ");
ValidateGarageXml(GetOriginalXml(), GetGarageXSD());
Console.WriteLine("Validating Fixed XML with original XSD: ");
ValidateGarageXml(GetFixedXml(), GetGarageXSD());
Console.WriteLine("Validating Fixed XML with added wrapper <Vehicles> element with XSD with added wrapper <Vehicles> element:");
ValidateGarageXml(GetFixedXmlWithWrapperElement(), GetGarageXSDWithWrapperElement());
var garage = GetFixedXmlWithWrapperElement().LoadFromXML<Garage>();
var reserializedXML = garage.GetXml();
Console.WriteLine("Result of deserializing and re-serializing Fixed XML with added wrapper <Vehicles> element: ");
Console.WriteLine(reserializedXML);
private static void ValidateGarageXml(string xml, string garageXsd)
XmlSchemaSet schema = new XmlSchemaSet();
using (var xsdReader = new StringReader(garageXsd))
schema.Add(XmlSchema.Read(xsdReader, null));
XDocument validateDoc = XDocument.Parse(xml);
var errors = new List<string>();
var flags = XmlSchemaValidationFlags.ReportValidationWarnings;
Console.WriteLine(validateDoc);
validateDoc.Validate(schema, flags, (o, ea) =>
Console.WriteLine("Passed Validation.");
Console.WriteLine("Failed Validation, errors:");
Console.WriteLine(String.Join("\n", errors));
static string GetGarageXSD()
var xsd = @"<?xml version=""1.0"" encoding=""utf-8""?>
<xs:schema attributeFormDefault=""unqualified"" elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"">
<xs:complexType name=""Vehicle"" abstract=""true"">
<xs:element name=""Manufacturer"" type=""xs:string"" nillable=""false"" />
<xs:complexType name=""Car"">
<xs:extension base=""Vehicle"">
<xs:element name=""Configuration"" type=""xs:string"" nillable=""false"" />
<xs:complexType name=""Truck"">
<xs:extension base=""Vehicle"">
<xs:element name=""Load"" type=""xs:int"" nillable=""false"" />
<xs:element name=""Garage"">
<xs:element name=""Vehicles"" type=""Vehicle"" minOccurs=""0"" maxOccurs=""unbounded"" nillable=""false"" />
static string GetGarageXSDWithWrapperElement()
var xsd = @"<?xml version=""1.0"" encoding=""utf-8""?>
<xs:schema attributeFormDefault=""unqualified"" elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"">
<xs:complexType name=""Vehicle"" abstract=""true"">
<xs:element name=""Manufacturer"" type=""xs:string"" nillable=""false"" />
<xs:complexType name=""Car"">
<xs:extension base=""Vehicle"">
<xs:element name=""Configuration"" type=""xs:string"" nillable=""false"" />
<xs:complexType name=""Truck"">
<xs:extension base=""Vehicle"">
<xs:element name=""Load"" type=""xs:int"" nillable=""false"" />
<xs:complexType name=""ArrayOfVehicle"">
<xs:element minOccurs=""0"" maxOccurs=""unbounded"" name=""Vehicle"" nillable=""true"" type=""Vehicle"" />
<xs:element name=""Garage"">
<xs:element minOccurs=""0"" maxOccurs=""1"" name=""Vehicles"" type=""ArrayOfVehicle"" />
public static class XNodeExtensions
public static void Validate(this XContainer node, XmlReaderSettings settings)
throw new ArgumentNullException();
using (var innerReader = node.CreateReader())
using (var reader = XmlReader.Create(innerReader, settings))
public static void Validate(this XContainer node, XmlSchemaSet schemaSet, XmlSchemaValidationFlags validationFlags, ValidationEventHandler validationEventHandler)
var settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= validationFlags;
if (validationEventHandler != null)
settings.ValidationEventHandler += validationEventHandler;
settings.Schemas = schemaSet;
public static void Main()
public static class XmlSerializationHelper
public static T LoadFromXML<T>(this string xmlString)
using (StringReader reader = new StringReader(xmlString))
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
public static string GetXml<T>(this T obj, bool omitStandardNamespaces = false)
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
ns = new XmlSerializerNamespaces();
using (var textWriter = new StringWriter())
var settings = new XmlWriterSettings() { Indent = true };
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();