Library / SDK
mganss/XmlSchemaClassGenerator avatar
mganss/XmlSchemaClassGenerator

XmlSchemaClassGenerator turns XSD files into XmlSerializer-ready C# classes

Generate C# classes from XML Schema files

765 stars216 forksHTMLApache-2.0

At a glance

What is it?
XmlSchemaClassGenerator is a console program and library that reads XML Schema and emits C# classes the XmlSerializer can use, with namespace mapping, DataAnnotations derived from schema restrictions, nullable adapters for optional members and optional Entity Framework Code First support. Its own list of unsupported features is longer and more specific than the feature list, which is the most useful thing in the README.
Who is it for?
Adopt XmlSchemaClassGenerator if you maintain an XML Schema and want strongly typed C# classes that the built-in XmlSerializer can consume, since the generator handles the mapping details that are tedious to write by hand and the output is regenerated from the schema. Skip it if your schema uses recursive choices or groups with maxOccurs greater than zero, because those are listed as unsupported and would need hand-written classes.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly HTML, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A console program and a library for the same job

XmlSchemaClassGenerator is a console program and library to generate XmlSerializer compatible C# classes from XML Schema files.

Being both is the design decision worth understanding. A library means you can call the generator from your own build or tooling, and the repository layout shows that split with a XmlSchemaClassGenerator/ directory for the library, a XmlSchemaClassGenerator.Console/ directory for the command line front end, a XmlSchemaClassGenerator.Tests/ directory, and a XmlSampleGenerator/ directory. The xscgen/ and xscgen-proj/ directories are the project files for the tool itself.

The target of the output is the .NET XmlSerializer, which is a demanding consumer. It needs classes with particular shapes, particular constructors and particular visibility rules, and hand-writing them from a schema is exactly the kind of work that is slow to do and worse to maintain. Generating them means the classes follow the schema, and a schema change produces a diff.

The badges show the target frameworks as netstandard2.0 and net462, which covers the older .NET Framework and the cross-platform standard, and the build is on AppVeyor with coverage on Codecov. The primary language is listed as HTML, which reflects the documentation site in the repository rather than the source, since the project file is named XmlSchemaClassGenerator.sln with a DotSettings file alongside it.

The releases are frequent and finely numbered, with v3.0.1405 from 2026-09-22, v3.0.1356 from 2026-07-21 and v3.0.1355 from 2026-07-20. The last push was on 2026-10-15.

The command line is a mapping tool as much as a generator

The usage output is worth reading, because most of the options are about mapping rather than about generation.

code
Usage: xscgen [OPTIONS]+ xsdFile...
Generate C# classes from XML Schema files.
Version ...
xsdFiles may contain globs, e.g. "content\{schema,xsd}\**\*.xsd", and URLs.
Append - to option to disable it, e.g. --interface-.

The last line is a nice touch. Every option can be negated by appending a hyphen, so a feature that is on by default can be turned off without a separate flag name. The example given is `--interface-`.

The namespace mapping options carry most of the configuration weight:

code
  -n, --namespace=VALUE      map an XML namespace to a C# namespace
  -o, --output=FOLDER        the FOLDER to write the resulting .cs files to
  -i, --integer=TYPE         map xs:integer and derived types to TYPE instead

The namespace option takes an XML namespace and a C# namespace separated by an equals sign, and a single value with no equals sign is taken as the C# namespace that the empty XML namespace maps to. One option must be given for each namespace to be mapped, and a file name may be given by appending a pipe sign followed by a file name, so schema.xsd. If no mapping is found for an XML namespace, a name is generated automatically, and the tool warns that this may fail.

The integer option is the type mapping override. xs:integer and derived types are mapped to the closest possible .NET type by default, with a fallback to string if that is not possible, and this option lets you choose the type explicitly, with the accepted values listed as sb, sh, i, l, ni, b, us, ui, ul, nui or d. A companion option uses the integer type only if no type can be deduced, which is the opposite default.

There are also file-based variants of the mapping options, one for namespaces and one for type name substitutions, both taking a file with one mapping per line, where lines starting with # and empty lines are ignored.

Type names need escaping and sometimes need substituting

One option deserves its own look because it addresses a real and common problem.

The `--typeNameSubstitute` option substitutes a generated type or member name. The type or member name and the substitute name are separated by an equals sign, and you prefix the type or member name with an appropriate kind ID. Prefixing with 'A:' substitutes any type or member.

The reason this exists is the unsupported features list, which includes possible name clashes and invalid identifiers when names contain non-alphanumeric characters. An XML Schema is free to name an element something like `order-item` or a type with a space in it, and neither survives as a C# identifier. The generator's automatic naming can therefore produce clashes or produce something that does not compile.

The substitute mechanism is the escape hatch. Rather than renaming elements in the schema, which you may not control if the schema comes from a partner or a regulator, you map the generated name to a legal C# one. The file variant, `--typeNameSubstituteFile`, holds the same mappings in a file, one per line, with the prefixed type or member name on the left of the equals sign.

The same concern appears in the namespace handling, where a schema namespace has to become a C# namespace, and where the generator can generate a name automatically but warns that this may fail. In practice, mapping the namespaces explicitly is the reliable path, which is why the tool requires one option per namespace to be mapped.

The generated classes carry DataAnnotations and nullable adapters

The feature list is long and the items fall into a few groups, and the C# language features are the ones that change how the output looks.

DataAnnotations attributes are generated from schema restrictions, and where a restriction is not covered by a standard DataAnnotations attribute, a custom attribute is generated instead. That is a complete answer to the restrictions problem rather than a partial one, which matters because a schema with a pattern or a length limit will otherwise produce a class that does not enforce what the schema promised.

Nullable reference types are supported through AllowNullAttribute and MaybeNullAttribute, and separately the generator produces nullable adapter properties for optional elements and attributes that have no default value. The adapter pattern is worth understanding, since it is a design decision rather than a feature flag. A plain nullable property makes the type system express optionality, but the XmlSerializer needs a non-nullable property it can set. An adapter property gives you both: a nullable property for your code and a serializable one for the serializer.

Other C# niceties: automatic properties, Pascal case for classes and properties, and Collection<T> properties for repeated elements, initialized in the constructor and with a private setter. The integer mapping described earlier is here too, with the fallback to string.

On the framework side there is optional support for PCL, optional support for INotifyPropertyChanged, optional support for Entity Framework Code First with automatically generated key properties, optionally generated interfaces for groups and attribute groups, optionally one file per class, and an option to generate a common specific type for union member types.

The unsupported list is the most important section

The README lists what it cannot do, and the list is specific enough to be actionable.

Some restriction types are unsupported, which is a partial gap in the DataAnnotations coverage.

Recursive choices and choices whose elements have minOccurs greater than zero or are nillable are unsupported, and the README links to a section on choices for the detail. This is the largest limitation, because a recursive choice is how a schema expresses a tree, and the generator cannot produce a C# class for it.

Possible name clashes and invalid identifiers when names contain non-alphanumeric characters are unsupported, which is the case the type name substitution option exists to work around.

Groups with maxOccurs greater than zero are unsupported, meaning a repeating group cannot be generated.

Put together, those four items describe a specific class of schema that this generator handles badly: a document with recursive structure, with repeated groups, with names that are not legal identifiers, and with restrictions that do not map to a standard attribute. If your schema looks like that, the honest advice is that you will be writing part of the classes by hand.

The nullable support and the DataAnnotations support, by contrast, are complete, and the choice handling is partial. That is a coherent shape for a generator: the common cases of a flat or nested document are fully covered, and the awkward structural cases are not.

Where it sits against the alternative approaches

The alternatives to a schema-driven generator are worth naming, because each is a reasonable choice in a different situation.

The first is hand-writing the classes. This is what many projects do, and it has one large advantage: the classes are yours, so you can add the behaviour that the schema cannot express. A schema describes a wire format, and a good domain model often differs from it. The disadvantage is that the classes drift from the schema silently, and the XmlSerializer's requirements make hand-writing slower than it should be.

The second is a runtime-binding approach, where you deserialize into a dynamic or dictionary-based structure and deal with the schema at runtime. That avoids the code generation step entirely and is a good fit when the schema is not known at build time, or when the shape changes often. It gives up compile-time checking, which is the main thing code generation buys you.

The third is a different generator. There are other XSD-to-C# tools, and the practical differences come down to the language feature support and the edge case coverage rather than the core job, which is the same. The DataAnnotations and nullable adapter support here is more thorough than a basic generator, and the substitution options for awkward names are a real advantage if your schema has awkward names.

The fourth possibility is generating from something other than XSD. If the real contract is a JSON schema, an OpenAPI document or a protocol buffer definition, a generator for that format is a better fit, because the C# class shape, the attributes and the serializer would all be consistent with the other tooling in your stack.

Editorial conclusion

Adopt XmlSchemaClassGenerator if you maintain an XML Schema and want strongly typed C# classes that the built-in XmlSerializer can consume, since the generator handles the mapping details that are tedious to write by hand and the output is regenerated from the schema. Skip it if your schema uses recursive choices or groups with maxOccurs greater than zero, because those are listed as unsupported and would need hand-written classes. Verify first that your target framework is netstandard2.0 or net462, that the namespaces in your schema can be mapped explicitly, and that the restrictions you rely on map to a DataAnnotations attribute or a generated custom attribute rather than being silently dropped.

Frequently asked questions

How do I install XmlSchemaClassGenerator?

Four routes are given: binary zips in the GitHub releases, binaries in the tools folder of the XmlSchemaClassGenerator.Console NuGet package, a .NET Core CLI tool from the dotnet-xscgen NuGet package, or CI builds from the AppVeyor NuGet feed. The tool targets netstandard2.0 and net462.

How do I map XML namespaces to C# namespaces?

Use the `-n, --namespace=VALUE` option, separating the XML namespace and the C# namespace with an equals sign. A single value with no equals sign is taken as the C# namespace for the empty XML namespace, and one option must be given for each namespace to be mapped. A file name can be appended after a pipe sign.

What can XmlSchemaClassGenerator not generate?

Some restriction types, recursive choices and choices whose elements have minOccurs greater than zero or are nillable, possible name clashes and invalid identifiers when names contain non-alphanumeric characters, and groups with maxOccurs greater than zero.

How do I override the .NET type used for xs:integer?

By default xs:integer and derived types are mapped to the closest possible .NET type, falling back to string. The `-i, --integer=TYPE` option sets the type explicitly, and the `--fallback` option uses that type only if no type can be deduced.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. mganss/XmlSchemaClassGenerator on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mganss-xmlschemaclassgenerator.svg)](https://hysenlabs.com/projects/mganss-xmlschemaclassgenerator)

Was this useful?