xml-schema code-generation C#
Need help with XmlSchemaClassGenerator?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.
mganss

Description

Generate C# classes from XML Schema files

249 Stars 117 Forks Apache License 2.0 552 Commits 20 Opened issues

Services available

Need anything else?

XmlSchemaClassGenerator

Nuget Build status codecov.io netstandard2.0 net461

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

Features

  • Map XML namespaces to C# namespaces, either explicitly or through a (configurable) function
  • Generate C# XML comments from schema annotations
  • Generate DataAnnotations attributes from schema restrictions
  • Use
    Collection
    properties (initialized in constructor and with private setter)
  • Map xs:integer and derived types to the closest possible .NET type, if not possible - fall back to string. Can be overriden by explicitly defined type (int, long, or decimal)
  • Automatic properties
  • Pascal case for classes and properties
  • Generate nullable adapter properties for optional elements and attributes without default values (see below)
  • Optional support for PCL
  • Optional support for
    INotifyPropertyChanged
  • Optional support for Entity Framework Code First (automatically generate key properties)
  • Optionally generate interfaces for groups and attribute groups
  • Optionally generate one file per class

Unsupported:

  • Some restriction types
  • Recursive choices and choices whose elements have minOccurs > 0 or nillable="true" (see below)
  • Possible name clashes and invalid identifiers when names contain non-alphanumeric characters
  • Groups with maxOccurs > 0

Usage

For command line use, choose your preferred installation: - Binary zips included in the releases on GitHub - Binaries in the tools folder in the console application NuGet package - .NET Core CLI tool available in the dotnet-xscgen NuGet package - CI Builds are available at the NuGet feed https://ci.appveyor.com/nuget/xmlschemaclassgenerator-0f1t3r6ti475

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

Options: -h, --help show this message and exit -n, --namespace=VALUE map an XML namespace to a C# namespace Separate XML namespace and C# namespace by '='. One option must be given for each namespace to be mapped. A file name may be given by appending a pipe sign (|) followed by a file name (like schema. xsd) to the XML namespace. If no mapping is found for an XML namespace, a name is generated automatically (may fail). -o, --output=FOLDER the FOLDER to write the resulting .cs files to -i, --integer=TYPE map xs:integer and derived types to TYPE instead of automatic approximation TYPE can be i[nt], l[ong], or d[ecimal]. --fb, --fallback, --use-integer-type-as-fallback use integer type specified via -i only if no type can be deduced -e, --edb, --enable-data-binding enable INotifyPropertyChanged data binding -r, --order emit order for all class members stored as XML element -c, --pcl PCL compatible output -p, --prefix=PREFIX the PREFIX to prepend to auto-generated namespace names -v, --verbose print generated file names on stdout -0, --nullable generate nullable adapter properties for optional elements/attributes w/o default values -f, --ef generate Entity Framework Code First compatible classes -t, --interface generate interfaces for groups and attribute groups (default is enabled) -a, --pascal use Pascal case for class and property names ( default is enabled) --av, --assemblyVisible use the internal visibility modifier (default is false) -u, --enableUpaCheck should XmlSchemaSet check for Unique Particle Attribution (UPA) (default is enabled) --ct, --collectionType=VALUE collection type to use (default is System. Collections.ObjectModel.Collection`1) --cit, --collectionImplementationType=VALUE the default collection type implementation to use ( default is null) --csm, --collectionSettersMode=Private, Public, PublicWithoutConstructorInitialization generate a private, public or public setters without backing field initialization for collections (default is Private; can be: Private, Public, PublicWithoutConstructorInitialization) --ctro, --codeTypeReferenceOptions=GlobalReference, GenericTypeParameter the default CodeTypeReferenceOptions Flags to use ( default is unset; can be: GlobalReference, GenericTypeParameter) --tvpn, --textValuePropertyName=VALUE the name of the property that holds the text value of an element (default is Value) --dst, --debuggerStepThrough generate DebuggerStepThroughAttribute (default is enabled) --dc, --disableComments do not include comments from xsd --nu, --noUnderscore do not generate underscore in private member name ( default is false) --da, --description generate DescriptionAttribute (default is true) --cc, --complexTypesForCollections generate complex types for collections (default is true) -s, --useShouldSerialize use ShouldSerialize pattern instead of Specified pattern (default is false) --sf, --separateFiles generate a separate file for each class (default is false) --dnfin, --doNotForceIsNullable do not force generator to emit IsNullable = true in XmlElement annotation for nillable elements when element is nullable (minOccurs < 1 or parent element is choice) (default is false)

For use from code use the library NuGet package:

var generator = new Generator
{
    OutputFolder = outputFolder,
    Log = s => Console.Out.WriteLine(s),
    GenerateNullables = true,
    NamespaceProvider = new Dictionary 
    { 
        { new NamespaceKey("http://wadl.dev.java.net/2009/02"), "Wadl" } 
    }
    .ToNamespaceProvider(new GeneratorConfiguration { NamespacePrefix = "Wadl" }.NamespaceProvider.GenerateNamespace)
};

generator.Generate(files);

Specifying the

NamespaceProvider
is optional. If you don't provide one, C# namespaces will be generated automatically. The example above shows how to create a custom
NamespaceProvider
that has a dictionary for a number of specific namespaces as well as a generator function for XML namespaces that are not in the dictionary. In the example the generator function is the default function but with a custom namespace prefix. You can also use a custom generator function, e.g.
var generator = new Generator
{
    NamespaceProvider = new NamespaceProvider
    { 
        GenerateNamespace = key => ...
    }
};

Mapping xsd files to C# namespaces

Using the optional

|
syntax of the
-n
command line option you can map individual xsd files to C# namespaces. If you have several input files using the same XML namespace you can still generate an individual C# namespace for the types defined within a single xsd file. For example, if you have two input files
a.xsd
and
b.xsd
both of which have the same
targetNamespace
of
http://example.com/namespace
you can generate the C# namespaces
Example.NamespaceA
and
Example.NamespaceB
:
dotnet-xscgen.exe -n "|a.xsd=Example.NamespaceA" -n "|b.xsd=Example.NamespaceB" a.xsd b.xsd

Mapping empty XML namespaces

In order to provide a C# namespace name for an empty XML namespace you can specify it on the command line like this:

XmlSchemaClassGenerator.Console.exe -n =Example example.xsd

Note the space between

-n
and
=Example
.

Nullables

XmlSerializer has been present in the .NET Framework since version 1.1 and has never been updated to provide support for nullables which are a natural fit for the problem of signaling the absence or presence of a value type but have only been present since .NET Framework 2.0.

Instead XmlSerializer has support for a pattern where you provide an additional bool property with "Specified" appended to the name to signal if the original property should be serialized. For example:

...
[System.Xml.Serialization.XmlAttributeAttribute("id", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="int")]
public int Id { get; set; }

[System.Xml.Serialization.XmlIgnoreAttribute()] public bool IdSpecified { get; set; }

XmlSchemaClassGenerator can optionally generate an additional nullable property that works as an adapter to both properties:

[System.Xml.Serialization.XmlAttributeAttribute("id", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="int")]
public int IdValue { get; set; }

[System.Xml.Serialization.XmlIgnoreAttribute()] public bool IdValueSpecified { get; set; }

[System.Xml.Serialization.XmlIgnoreAttribute()] public System.Nullable Id { get { if (this.IdValueSpecified) { return this.IdValue; } else { return null; } } set { this.IdValue = value.GetValueOrDefault(); this.IdValueSpecified = value.HasValue; } }

Choice Elements

The support for choice elements differs from that provided by xsd.exe. Xsd.exe generates a property called

Item
of type
object
and, if not all choices have a distinct type, another enum property that selects the chosen element. Besides being non-typesafe and non-intuitive, this approach breaks apart if the choices have a more complicated structure (e.g. sequences), resulting in possibly schema-invalid XML.

XmlSchemaClassGenerator currently simply pretends choices are sequences. This means you'll have to take care only to set a schema-valid combination of these properties to non-null values.

Interfaces

Groups and attribute groups in XML Schema are reusable components that can be included in multiple type definitions. XmlSchemaClassGenerator can optionally generate interfaces from these groups to make it easier to access common properties on otherwise unrelated classes. So

  



  



  

becomes

public partial interface ICommon
{
  string Name { get; set; }
}

public partial class A: ICommon { public string Name { get; set; } }

public partial class B: ICommon { public string Name { get; set; } }

Collection types

Values for the

--collectionType
and
--collectionImplementationType
options have to be given in the format accepted by the
Type.GetType()
method. For the
System.Collections.Generic.List
class this means
System.Collections.Generic.List`1
.

Integer and derived types

Not all numeric types defined by XML Schema can be safely and accurately mapped to .NET numeric data types, however, it's possible to approximate the mapping based on the integer bounds and restrictions such as

totalDigits
.
If an explicit integer type mapping is specified via
--integer=TYPE
, that type will be used, otherwise an approximation will be made based on the table below. If you additionally specify
--fallback
, the type specified via
--integer=TYPE
will be used only if no type can be deduced by applying the rules below.

If the restrictions

minInclusive
and
maxInclusive
are present on the integer element, then the smallest CLR type that fully encompasses the specified range will be used. Unsigned types are given precedence over signed types. The following table shows the possible ranges and their corresponding CLR type, in the order they will be applied.
Minimum (Inclusive) Maximum (Inclusive) C# type
sbyte.MinValue sbyte.MaxValue sbyte
byte.MinValue byte.MaxValue byte
ushort.MinValue ushort.MaxValue ushort
short.MinValue short.MaxValue short
uint.MinValue uint.MaxValue uint
int.MinValue int.MaxValue int
ulong.MinValue ulong.MaxValue ulong
long.MinValue long.MaxValue long
decimal.MinValue decimal.MaxValue decimal

If the range specified by

minInclusive
and
maxInclusive
does not fit in any CLR type, or if those restrictions are not present, then the
totalDigits
restriction will be used, as shown in the following table.
XML Schema type totalDigits C# type
xs:positiveInteger
xs:nonNegativeInteger
<3 byte
<5 ushort
<10 uint
<20 ulong
<30 decimal
>=30 string
xs:integer
xs:nonPositiveInteger
xs:negativeInteger
<3 sbyte
<5 short
<10 int
<19 long
<29 decimal
>=29 string

Contributing

Contrbutions are welcome. Here are some guidelines:

  • If it's not a trivial fix, please submit an issue first
  • Try and blend new code with the existing code's style
  • Add unit tests

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.