NV ToolkitFormat · Validate · Convert

Code Generators

XML to C# Converter

Paste an XML sample, get typed C# models — names, nesting and nullability inferred for you.

In short

Convert XML to C# online: paste a sample and generate typed C# models with serialization helpers — powered by quicktype, in your browser.

By NaveenKumar T · Updated

Learn: XML Tutorial: Structure, Syntax & Survival Skills

  • Typed models from one sample
  • Nested objects become types
  • Nullability inferred

Runs entirely in your browser — nothing you paste or open here is uploaded, logged, or stored.How we handle data →

Example

Example: XML order payload to C#

The same order as XML, with data split between attributes (id, status, paid, sku, qty, price) and element text (name, email, total) — the split that decides which C# fields are typed as numbers and which stay strings. The right-hand side is the exact output of this tool.

Input · XML
<order id="ord_9F2KX" status="processing" paid="true">
  <customer>
    <name>Ada Lovelace</name>
    <email>ada@example.com</email>
  </customer>
  <items>
    <item sku="KB-75" qty="1" price="149.99"/>
    <item sku="MS-12" qty="2" price="39.5"/>
  </items>
  <total>228.99</total>
</order>
Generated · C#
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
//    using QuickType;
//
//    var root = Root.FromJson(jsonString);

namespace QuickType
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class Root
    {
        [JsonProperty("order")]
        public Order Order { get; set; }
    }

    public partial class Order
    {
        [JsonProperty("customer")]
        public Customer Customer { get; set; }

        [JsonProperty("items")]
        public Items Items { get; set; }

        [JsonProperty("total")]
        public double Total { get; set; }

        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("status")]
        public string Status { get; set; }

        [JsonProperty("paid")]
        [JsonConverter(typeof(FluffyParseStringConverter))]
        public bool Paid { get; set; }
    }

    public partial class Customer
    {
        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("email")]
        public string Email { get; set; }
    }

    public partial class Items
    {
        [JsonProperty("item")]
        public Item[] Item { get; set; }
    }

    public partial class Item
    {
        [JsonProperty("sku")]
        public string Sku { get; set; }

        [JsonProperty("qty")]
        [JsonConverter(typeof(PurpleParseStringConverter))]
        public long Qty { get; set; }

        [JsonProperty("price")]
        public string Price { get; set; }
    }

    public partial class Root
    {
        public static Root FromJson(string json) => JsonConvert.DeserializeObject<Root>(json, QuickType.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this Root self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }

    internal class PurpleParseStringConverter : JsonConverter
    {
        public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);

        public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null) return null;
            var value = serializer.Deserialize<string>(reader);
            long l;
            if (Int64.TryParse(value, out l))
            {
                return l;
            }
            throw new Exception("Cannot unmarshal type long");
        }

        public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
        {
            if (untypedValue == null)
            {
                serializer.Serialize(writer, null);
                return;
            }
            var value = (long)untypedValue;
            serializer.Serialize(writer, value.ToString());
            return;
        }

        public static readonly PurpleParseStringConverter Singleton = new PurpleParseStringConverter();
    }

    internal class FluffyParseStringConverter : JsonConverter
    {
        public override bool CanConvert(Type t) => t == typeof(bool) || t == typeof(bool?);

        public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null) return null;
            var value = serializer.Deserialize<string>(reader);
            bool b;
            if (Boolean.TryParse(value, out b))
            {
                return b;
            }
            throw new Exception("Cannot unmarshal type bool");
        }

        public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
        {
            if (untypedValue == null)
            {
                serializer.Serialize(writer, null);
                return;
            }
            var value = (bool)untypedValue;
            var boolString = value ? "true" : "false";
            serializer.Serialize(writer, boolString);
            return;
        }

        public static readonly FluffyParseStringConverter Singleton = new FluffyParseStringConverter();
    }
}

Compare "total" (element text, typed double) with "price" (an attribute, kept as string) — while "qty" and "paid" carry a JsonConverter that parses them into long and bool. The root <order> element became a nested Order type under Root.

Learn more

From XML sample to C# types

Hand-writing model classes from an XML payload means deciding, field by field, which parser reads which node — this page automates that decision. quicktype first parses your document into a data model, attributes included, then runs the same type inference it uses for JSON against the result.

The generated Converter.Settings sets DateParseHandling.None on purpose: with Newtonsoft's default, every ISO-8601 string in the payload would silently become a DateTime and serialize back in a different format. Keep that setting when you build your own JsonSerializerSettings, or convert dates deliberately with a JsonConverter on the fields that really are dates.

How XML elements and attributes become C# types

The XML is parsed into a data model before inference (attributes included, text nodes named "text"), so the root element becomes a nested type: <order> is a field of type Order on the top-level Root rather than the top level itself. Child elements become fields, and repeated elements — the two <item> siblings — are collected into Item[] under an Items wrapper type that mirrors the <items> container.

Attributes and element text are typed differently, and this matters: element text is type-inferred, so <total>228.99</total> becomes double, while attribute values arrive as strings and C# is one of only two targets that converts them back: price="149.99" stays string, while qty="1" is typed long and paid="true" bool, each through a generated ParseStringConverter. Prefer element text for numeric data you want typed, or cast attribute values after decoding. One more trap: a single <item> would not be recognized as a list, so make sure repeated elements appear at least twice in the sample.

Read XML in C# with the generated classes

XmlSerializer cannot use these classes: it wants [XmlRoot] and [XmlElement] attributes, and the generator emits Newtonsoft's [JsonProperty] instead. The honest route is to convert first — load the document into an XmlDocument, let JsonConvert.SerializeXmlNode turn it into JSON, then call the generated Root.FromJson. Plan for one wrinkle: Newtonsoft writes XML attributes with an "@" prefix, so id arrives as "@id" and matches no generated property until you strip it. Elements are unaffected, and repeated elements become the array the models expect.

C# · XmlDocument to JSON
using System.Xml;
using Newtonsoft.Json;

var doc = new XmlDocument();
doc.LoadXml(xmlString);

// Newtonsoft prefixes attributes with "@" — the generated names have none.
var json = JsonConvert.SerializeXmlNode(doc).Replace("\"@", "\"");

Root root = Root.FromJson(json);
Console.WriteLine(root.Order.Items.Item[0].Sku); // KB-75

Help

Frequently asked questions

Everything you need to know about the XML to C#.

01How do I generate C# classes from XML?

Paste an XML document and press Convert. It is first parsed into a data model — attributes included — then typed: the root element becomes a nested type, repeated elements become Item[], and the result downloads as Root.cs.

02Can XmlSerializer use these classes?

XmlSerializer cannot use them as generated — it needs [XmlRoot]/[XmlElement] attributes and the generator emits Newtonsoft's [JsonProperty] instead. Load the XML into an XmlDocument, convert with JsonConvert.SerializeXmlNode, strip the "@" that Newtonsoft prefixes onto attribute names, and call the generated Root.FromJson.

03Why are qty and paid typed long and bool when they are attributes?

C# is one of two targets that parse attribute strings back into numbers and booleans, through a generated ParseStringConverter; price stays string because 149.99 is not a whole number. Element text such as total is type-inferred as double.

04Does an empty XML element like <notes/> become null or an empty string in C#?

Neither predictably — JsonConvert.SerializeXmlNode renders a self-closing element as null in the intermediate JSON, so the generated property ends up null just as an absent field would, not an empty string. If the distinction between empty and missing matters, check for the element's presence in the XmlDocument before conversion rather than trusting the generated model alone.

Keep working

Related tools

Learn the format

Related guides

All guides →