Git Product home page Git Product logo

xmlschemaclassgenerator's Introduction

XmlSchemaClassGenerator

Nuget Build status codecov.io netstandard2.0 net462

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<T> 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
  • Support for nullable reference types (NRTs) through AllowNullAttribute and MaybeNullAttribute
  • Optionally generate a common specific type for union member types

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:

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-.

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 '='.
                               A single value (no '=') is taken as the C#
                               namespace the empty XML namespace is mapped to.
                               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).
      --nf, --namespaceFile=VALUE
                             file containing mappings from XML namespaces to C#
                               namespaces
                               The line format is one mapping per line: XML
                               namespace = C# namespace [optional file name].
                               Lines starting with # and empty lines are
                               ignored.
      --tns, --typeNameSubstitute=VALUE
                             substitute a generated type/member name
                               Separate type/member name and substitute name by
                               '='.
                               Prefix type/member name with an appropriate kind
                               ID as documented at: https://t.ly/HHEI.
                               Prefix with 'A:' to substitute any type/member.
      --tnsf, --typeNameSubstituteFile=VALUE
                             file containing generated type/member name
                               substitute mappings
                               The line format is one mapping per line:
                               prefixed type/member name = substitute name.
                               Lines starting with # and empty lines are
                               ignored.
  -o, --output=FOLDER        the FOLDER to write the resulting .cs files to
  -d, --datetime-offset      map xs:datetime and derived types to System.
                               DateTimeOffset instead of System.DateTime
  -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, Init, InitWithoutConstructorInitialization
                             generate a private, public, or init-only setter
                               with or without backing field initialization for
                               collections
                               (default is Private; can be: Private, Public,
                               PublicWithoutConstructorInitialization, Init,
                               InitWithoutConstructorInitialization)
      --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)
      --nh, --namespaceHierarchy
                             generate a separate folder for namespace hierarchy.
                                Implies "separateFiles" if true (default is
                               false)
      --sg, --separateSubstitutes
                             generate a separate property for each element of a
                               substitution group (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)
      --cn, --compactTypeNames
                             use type names without namespace qualifier for
                               types in the using list (default is false)
      --cl, --commentLanguages=VALUE
                             comment languages to use (default is en; supported
                               are en, de)
      --un, --uniqueTypeNames
                             generate type names that are unique across
                               namespaces (default is false)
      --gc, --generatedCodeAttribute
                             add version information to GeneratedCodeAttribute (
                               default is true)
      --nc, --netCore        generate .NET Core specific code that might not
                               work with .NET Framework (default is false)
      --nr, --nullableReferenceAttributes
                             generate attributes for nullable reference types (
                               default is false)
      --ar, --useArrayItemAttribute
                             use ArrayItemAttribute for sequences with single
                               elements (default is true)
      --es, --enumAsString   Use string instead of enum for enumeration
      --ca, --commandArgs    generate a comment with the exact command line
                               arguments that were used to generate the source
                               code (default is true)
      --uc, --unionCommonType
                             generate a common type for unions if possible (
                               default is false)
      --dtd, --allowDtdParse
                             allow DTD parsing (default is false)
      --ns, --namingScheme   use the specified naming scheme for class and
                               property names (default is Pascal; can be:
                               Direct, Pascal, Legacy)

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<NamespaceKey, string> 
    { 
        { 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:

xscgen -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:

xscgen -n Example example.xsd

An alternative form that is also valid is -n =Example. Note the space between -n and =Example.

Using mapping files

Instead of specifying the namespace mappings on the command line you can also use a mapping file which should contain one mapping per line in the following format:

# Comment

http://example.com = Example.NamespaceA a.xsd
http://example.com = Example.NamespaceB b.xsd
Empty
# or alternatively
= Empty

Use the --nf option to specify the mapping file.

Substituting generated C# type and member names

If a xsd file specifies obscure names for their types (classes, enums) or members (properties), you can substitute these using the --tns/--typeNameSubstitute= parameter:

xscgen --tns T:Example_RootType=Example --tns T:Example_RootTypeExampleScope=ExampleScope --tns P:StartDateDateTimeValue=StartDate example.xsd

The syntax for substitution is: {kindId}:{generatedName}={substituteName}

The {kindId} is a single character identifier based on documentation/analysis ID format, where valid values are:

ID Scope
P Property
T Type: class, enum, interface
A Any property and/or type

Using substitution files

Instead of specifying the substitutions on the command line you can also use a substitution file which should contain one substitution per line in the following format:

# Comment
T:Example_RootType = Example
T:Example_RootTypeExampleScope = ExampleScope
P:StartDateDateTimeValue = StartDate

Use the --tnsf/--typeNameSubstituteFile option to specify the substitution file.

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:

<xs:attribute name="id" type="xs:int" use="optional">...</xs:attribute>
[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<int> 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

<xs:attributeGroup name="Common">
  <xs:attribute name="name" type="xs:string"></xs:attribute>
</xs:attributeGroup>

<xs:complexType name="A">
  <xs:attributeGroup ref="Common"/>
</xs:complexType>

<xs:complexType name="B">
  <xs:attributeGroup ref="Common"/>
</xs:complexType>

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<T> 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.MinValuesbyte.MaxValuesbyte
byte.MinValuebyte.MaxValuebyte
ushort.MinValueushort.MaxValueushort
short.MinValueshort.MaxValueshort
uint.MinValueuint.MaxValueuint
int.MinValueint.MaxValueint
ulong.MinValueulong.MaxValueulong
long.MinValuelong.MaxValuelong
decimal.MinValuedecimal.MaxValuedecimal

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
<3byte
<5ushort
<10uint
<20ulong
<30decimal
>=30string
xs:integer
xs:nonPositiveInteger
xs:negativeInteger
<3sbyte
<5short
<10int
<19long
<29decimal
>=29string

Unions

If you specify --unionCommonType, XmlSchemaClassGenerator will try to determine a common type for a union's member types. If, for example, the member types are all integer types, then the narrowest integer type will be used that can fit all member types.

Note that semantic issues might arise with this approach. For example, DateTime values are serialized with both date and time information included. See discussion at #397.

Contributing

Contributions 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

xmlschemaclassgenerator's People

Contributors

0xced avatar avtit avatar bcallaghan-et avatar cameronam avatar canton7 avatar dafanasiev avatar daviddays avatar dependabot-preview[bot] avatar dependabot[bot] avatar dimsday avatar fgheysels avatar filippobottega avatar flcdrg avatar fubar-coder avatar jaroslaw-dutka avatar jmatss avatar jokokko avatar kronic avatar las-nsc avatar lokimidgard avatar markokacprzak avatar mganss avatar redx2501 avatar shaynevanasperen avatar stilettk avatar tomcollaboration avatar travislaborde avatar twsouthwick avatar verdie-g avatar wetzel-fabian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xmlschemaclassgenerator's Issues

Comments added to the documentation

It would nice if there was a way to have comments like these:

<xs:attribute name="Created" type="xs:dateTime">
<xs:annotation>
<xs:documentation>Date/time the request was created.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ID" type="xs:string">
<xs:annotation>
<xs:documentation>
Identifier may be provided by client application for internal use/diagnostics.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<!--
 ATTRIBUTE DETAILS
                Created: When the Report request was created using format "yyyy-mm-dd hh:mm:ss"
                ID: Identifier of the request as assigned by the requesting service for internal use.

-->
</xs:complexType>

or these

<!--

 EISSN is not an "official" identifier type, but included for backward compatibility. Use Online_ISSN 
-->
<xsd:enumeration value="EISSN"/>

included in the documentation of the generated code

dotnet-xscgen incompatible with dotnet core 2.1

I'm trying to use the dotnet cli tool in my project, but it's a dotnet core 2.1 project.
And I'm getting the following error:

NU1202: Package dotnet-xscgen 2.0.106 is not compatible with netcoreapp2.1 (.NETCoreApp,Version=v2.1). Package dotnet-xscgen 2.0.106 supports:

  • net45 (.NETFramework,Version=v4.5) / any
  • netcoreapp2.0 (.NETCoreApp,Version=v2.0) / any

Could you update the dependencies and push a new package?

I find it strange that a dotnet tool has a specific dependency with the project it's used in. Since they are actually independent.

"Getting default value for OC not supported" error

I am trying to generate these XSDs (http://www.iata.org/whatwedo/airline-distribution/ndc/Pages/schema-download2.aspx)

This command dotnet XmlSchemaClassGenerator.Console.dll edist_commontypes.xsd edist_structures.xsd

generates

Unhandled Exception: System.NotSupportedException: Getting default value for OC not supported.
   at XmlSchemaClassGenerator.TypeModel.GetDefaultValueFor(String defaultString) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\TypeModel.cs:line 166
   at XmlSchemaClassGenerator.PropertyModel.AddMembersTo(CodeTypeDeclaration typeDeclaration, Boolean withDataBinding) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\TypeModel.cs:line 680
   at XmlSchemaClassGenerator.ClassModel.Generate() in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\TypeModel.cs:line 349
   at XmlSchemaClassGenerator.NamespaceModel.Generate(String namespaceName, IEnumerable`1 parts) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\TypeModel.cs:line 54
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\Generator.cs:line 197
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator.Console\Program.cs:line 134

Generated code can contain duplicate interfaces in base class list

After spending more than 30 minutes, I was unable to to produce an SSCCE. I do know that the MISMO v3.3 Residential Reference Model Schema can be used to reproduce the issue.

More specifically, the issue can be reproduced by running XmlSchemaClassGenerator agaisnt the "MISMO_3.3.0_B299.xsd" file in the "combined" sub-directory within the archive available for download at the link above. Unfortunately, I cannot post a copy of that XSD without violating their terms of use, but you can easily download it yourself after completing their form (sorry... I know that's a pain). The follow code excerpt begins on line 204 of the generated output c# code file:

    ...

    /// <summary>
    /// <para>A data type of String SHOULD identify a data point that is either a text value consisting of a word, phrase, sentence, paragraph, or formatted (TAB, CR, LF) character content depending on its purpose or a numeric value with a maximum of 16383 characters and MAY have the lang attribute. There is no list of valid values provided.
    ///EXAMPLE: A Disqualificaton Reason Text for excluding a product from those offered to a borrower could be expressed as "Does not meet income to indebtedness guidelines for down payment support.".</para>
    /// </summary>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("XmlSchemaClassGenerator", "1.0.58.0")]
    [System.SerializableAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute("MISMOString", Namespace="http://www.mismo.org/residential/2009/schemas")]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    public partial class MISMOString : Xlink.IMISMOresourceLink, IAttributeExtension, IAttributeExtension,
    {
    ...     

The MISMOString class implements the IAttributeExtension twice which produces a compilation error.

Exception: 'http://www.w3.org/2001/XMLSchema:sequence' element is not supported in this context.

I am looking to generate a set of classes off of the following XSD file
http://www.zillow.com/static/xsd/ZillowTypes.xsd

and I am running in to the following exception below

Unhandled Exception: System.Xml.Schema.XmlSchemaException: The 'http://www.w3.org/2001/XMLSchema:sequence' element is not supported in this context.
   at System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
   at System.Xml.Schema.XmlSchemaSet.ParseSchema(String targetNamespace, XmlReader reader)
   at System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace, String schemaUri)
   at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files)
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args)

Any thoughts?

Namespace not provided through map or generator

Hi,

I'm trying to convert this .xsd to c# class... I get an exception when trying to convert it. i'm not an XML or XSD expert so I don't know what exactly am I looking for...

Unhandled Exception: System.Exception: Namespace http://www.w3.org/2000/09/xmldsig# not provided through map or generator.
   at XmlSchemaClassGenerator.ModelBuilder.BuildNamespace(Uri source, String xmlNamespace)
   at XmlSchemaClassGenerator.ModelBuilder.CreateNamespaceModel(Uri source, XmlQualifiedName qualifiedName)
   at XmlSchemaClassGenerator.ModelBuilder.CreateTypeModel(Uri source, XmlSchemaAnnotated type, XmlQualifiedName qualifiedName)
   at XmlSchemaClassGenerator.ModelBuilder..ctor(GeneratorConfiguration configuration, XmlSchemaSet set)
   at XmlSchemaClassGenerator.Generator.Generate(XmlSchemaSet set)
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args)

is there anything that can be done?
Thanks!

.NET Standard support

The project currently targets .NET 4.5, making it difficult to use with .NET Standard class libraries. It would be good if this could be ported to a suitably low .NET Standard version.

dotnet cli unable to find matching command

Installed with dotnet tool install --global dotnet-xscgen but the cli is unable to find the xscgen tool.

C:\Users\daniel>dotnet --version
2.1.301

C:\Users\daniel>dotnet tool list -g
Package Id         Version      Commands
-----------------------------------------
dotnet-ef          2.1.1        dotnet-ef
dotnet-xscgen      2.0.142      xscgen

C:\Users\daniel>dotnet xscgen
No executable found matching command "dotnet-xscgen"

Namespace mapping with includes

When including files with only types and no elements, the namespaces won't get mapped properly. This is due to the fact, that in Generator.BuildModel(), the GlobalElements get processed before the GlobalTypes. I swapped the order to get it working and had no problems using it.

Before, all included types got included into the namespace of the includer. Therefore, I ended with multiple copies of the same type, distributed between different namespaces.

XSD is Valid but dotnet-xscgen.exe throws Unhandled exception. System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.

Some time ago I used XSD.exe

xsd.exe nfe_v4.00.xsd xmldsig-core-schema_v1.01.xsd /c /edb

Now I am trying to use XmlSchemaClassGenerator,
Using this XSDs
http://www.nfe.fazenda.gov.br/portal/exibirArquivo.aspx?conteudo=xLaRDcJryNA=

I run:

dotnet-xscgen.exe nfe_v4.00.xsd xmldsig-core-schema_v1.01.xsd

Then this Exception occurs:

Unhandled exception: System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
   em System.Xml.XmlTextReaderImpl.Throw(Exception e)
   em System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
   em System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   em System.Xml.Schema.Parser.StartParsing(XmlReader reader, String targetNamespace)
   em System.Xml.Schema.XmlSchema.Read(XmlReader reader, ValidationEventHandler validationEventHandler)
   em XmlSchemaClassGenerator.Generator.<>c__DisplayClass82_0.<Generate>b__0(String f)
   em System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   em XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files)
   em XmlSchemaClassGenerator.Console.Program.Main(String[] args)

Can you give a try, using the XSDs provided on the link above?

FileNotFoundException when running from command line

I installed the dotnet core CLI tool via dotnet tool install --global dotnet-xscgen --version 2.0.106 and it reportedly installed correctly. But when trying to run something like dotnet xscgen -h
I get the following output.
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'C:\Users\kennethearl\.dotnet\tools\dotnet-xscgen.dll'. The system cannot find the file specified.

Stack overflow when handling redefinition of complex type

Hi,

I'm trying to generate code from the following example. Schema1.xsd:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:complexType name="pname">
  <xs:sequence>
    <xs:element name="firstname"/>
    <xs:element name="lastname"/>
  </xs:sequence>
</xs:complexType>

<xs:element name="customer" type="pname"/>

</xs:schema>

Schema2.xsd:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:redefine schemaLocation="Schema1.xsd">
  <xs:complexType name="pname">
    <xs:complexContent>
      <xs:extension base="pname">
        <xs:sequence>
          <xs:element name="country"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:redefine>

<xs:element name="author" type="pname"/>

</xs:schema>

My generator program looks as follows:

using System.Collections.Generic;
using XmlSchemaClassGenerator;

namespace ClassGenerator
{
    internal class Program
    {
        internal static void Main(string[] args)
        {
            var generator = new Generator
            {
                OutputFolder = "",
                NamespacePrefix = "Output",
            };
            generator.Generate(new List<string>(new[] {"Schema2.xsd"}));
        }
    }
}

However, when running it, it throws the error:

An unhandled exception of type 'System.StackOverflowException' occurred in Unknown Module. occurred

I have managed to locate that it occurs in the class TypeModel in the method GetAllDerivedTypes, https://github.com/mganss/XmlSchemaClassGenerator/blob/master/XmlSchemaClassGenerator/TypeModel.cs#L401. It gets stuck there in an infinite recursive loop.

Would it be possible/easy to implement support for .xsd files that redefine complex types?

Unhandled Exception: System.Xml.Schema.XmlSchemaException: The global element has already been declared.

Folder aa contains A.xsd, B.xsd, C.xsd and D.xsd like in examples:
http://www.xfront.com/Dealing-With-Multiple-XML-Schema-Files.pdf

Executing:
XmlSchemaClassGenerator.Console.exe -p test aa\*.xsd

generate error:
Unhandled Exception: System.Xml.Schema.XmlSchemaException: The global element 'B' has already been declared.
at System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
at System.Xml.Schema.BaseProcessor.AddToTable(XmlSchemaObjectTable table, XmlQualifiedName qname, XmlSchemaObject item)
at System.Xml.Schema.Compiler.Prepare(XmlSchema schema, Boolean cleanup)
at System.Xml.Schema.XmlSchemaSet.Compile()
at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files)
at XmlSchemaClassGenerator.Console.Program.Main(String[] args)

aa.zip

Namespace not provided through map or generator

I try to translate a .xsd file to a .cs file, but I get the error message:

Unhandled Exception: System.Exception: Namespace http://myNamespace/StandardLdapSchema.xsd not provided through map or generator.
at XmlSchemaClassGenerator.Generator.BuildNamespace(Uri source, String xmlNamespace)
at XmlSchemaClassGenerator.Generator.CreateNamespaceModel(Uri source, XmlQualifiedName qualifiedName)
at XmlSchemaClassGenerator.Generator.CreateTypeModel(Uri source, XmlSchemaAnnotated type, XmlQualifiedName qualifiedN
ame)
at XmlSchemaClassGenerator.Generator.BuildModel()
at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files)
at XmlSchemaClassGenerator.Console.Program.Main(String[] args)

It is probably due to the import:

<xs:schema attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:att="http://myNamespace/Attributes.xsd"
           xmlns:ldap="http://myNamespace/StandardLdapSchema.xsd"
           targetNamespace="http://myNamespace/UtLdapSchema.xsd"
           xmlns="http://myNamespace/UtLdapSchema.xsd"
           >
  <xs:import schemaLocation="StandardLdapSchema.xsd" namespace="http://myNamespace/StandardLdapSchema.xsd" />
(...)
</xs:schema>

Is there a way I can fix this?

Curious error in generating from Open NDC Schema

reference http://www.iata.org/whatwedo/airline-distribution/ndc/Pages/schema-download2.aspx

I am able to run this command dotnet XmlSchemaClassGenerator.Console.dll *.xsd -o output -n http://www.iata.org/IATA/EDIST/2017.2=IATA if only this file xmldsig-core-schema.xsd is removed.

If xmldsig-core-schema.xsd is included, it will generate

Unhandled Exception: System.Exception: Namespace  not provided through map or generator.
   at XmlSchemaClassGenerator.Generator.BuildNamespace(Uri source, String xmlNamespace) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\Generator.cs:line 241
   at XmlSchemaClassGenerator.Generator.CreateNamespaceModel(Uri source, XmlQualifiedName qualifiedName) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\Generator.cs:line 780
   at XmlSchemaClassGenerator.Generator.CreateTypeModel(Uri source, XmlSchemaAnnotated type, XmlQualifiedName qualifiedName) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\Generator.cs:line 339
   at XmlSchemaClassGenerator.Generator.BuildModel() in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\Generator.cs:line 267
   at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator\Generator.cs:line 199
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator.Console\Program.cs:line 137

This is the content of xmldsig-core-schema.xsd

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd" [
	<!ATTLIST schema
		xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#"
	>
	<!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
	<!ENTITY % p ''>
	<!ENTITY % s ''>
]>
<!-- Schema for XML Signatures
    http://www.w3.org/2000/09/xmldsig#
    $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $

    Copyright 2001 The Internet Society and W3C (Massachusetts Institute
    of Technology, Institut National de Recherche en Informatique et en
    Automatique, Keio University). All Rights Reserved.
    http://www.w3.org/Consortium/Legal/

    This document is governed by the W3C Software License [1] as described
    in the FAQ [2].

    [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
    [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
-->
<ns1:schema xmlns:ns1="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="0.1">
	<!-- Basic Types Defined for Signatures -->
	<ns1:simpleType name="CryptoBinary">
		<ns1:restriction base="ns1:base64Binary"/>
	</ns1:simpleType>
	<!-- Start Signature -->
	<ns1:element name="Signature" type="SignatureType"/>
	<ns1:complexType name="SignatureType">
		<ns1:sequence>
			<ns1:element ref="SignedInfo"/>
			<ns1:element ref="SignatureValue"/>
			<ns1:element ref="KeyInfo" minOccurs="0"/>
			<ns1:element ref="Object" minOccurs="0" maxOccurs="unbounded"/>
		</ns1:sequence>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
	</ns1:complexType>
	<ns1:element name="SignatureValue" type="SignatureValueType"/>
	<ns1:complexType name="SignatureValueType">
		<ns1:simpleContent>
			<ns1:extension base="ns1:base64Binary">
				<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
			</ns1:extension>
		</ns1:simpleContent>
	</ns1:complexType>
	<!-- Start SignedInfo -->
	<ns1:element name="SignedInfo" type="SignedInfoType"/>
	<ns1:complexType name="SignedInfoType">
		<ns1:sequence>
			<ns1:element ref="CanonicalizationMethod"/>
			<ns1:element ref="SignatureMethod"/>
			<ns1:element ref="Reference" maxOccurs="unbounded"/>
		</ns1:sequence>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
	</ns1:complexType>
	<ns1:element name="CanonicalizationMethod" type="CanonicalizationMethodType"/>
	<ns1:complexType name="CanonicalizationMethodType" mixed="true">
		<ns1:sequence>
			<ns1:any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
			<!-- (0,unbounded) elements from (1,1) namespace -->
		</ns1:sequence>
		<ns1:attribute name="Algorithm" type="ns1:anyURI" use="required"/>
	</ns1:complexType>
	<ns1:element name="SignatureMethod" type="SignatureMethodType"/>
	<ns1:complexType name="SignatureMethodType" mixed="true">
		<ns1:sequence>
			<ns1:element name="HMACOutputLength" type="HMACOutputLengthType" minOccurs="0"/>
			<ns1:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
			<!-- (0,unbounded) elements from (1,1) external namespace -->
		</ns1:sequence>
		<ns1:attribute name="Algorithm" type="ns1:anyURI" use="required"/>
	</ns1:complexType>
	<!-- Start Reference -->
	<ns1:element name="Reference" type="ReferenceType"/>
	<ns1:complexType name="ReferenceType">
		<ns1:sequence>
			<ns1:element ref="Transforms" minOccurs="0"/>
			<ns1:element ref="DigestMethod"/>
			<ns1:element ref="DigestValue"/>
		</ns1:sequence>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
		<ns1:attribute name="URI" type="ns1:anyURI" use="optional"/>
		<ns1:attribute name="Type" type="ns1:anyURI" use="optional"/>
	</ns1:complexType>
	<ns1:element name="Transforms" type="TransformsType"/>
	<ns1:complexType name="TransformsType">
		<ns1:sequence>
			<ns1:element ref="Transform" maxOccurs="unbounded"/>
		</ns1:sequence>
	</ns1:complexType>
	<ns1:element name="Transform" type="TransformType"/>
	<ns1:complexType name="TransformType" mixed="true">
		<ns1:choice minOccurs="0" maxOccurs="unbounded">
			<ns1:any namespace="##other" processContents="lax"/>
			<!-- (1,1) elements from (0,unbounded) namespaces -->
			<ns1:element name="XPath" type="ns1:string"/>
		</ns1:choice>
		<ns1:attribute name="Algorithm" type="ns1:anyURI" use="required"/>
	</ns1:complexType>
	<!-- End Reference -->
	<ns1:element name="DigestMethod" type="DigestMethodType"/>
	<ns1:complexType name="DigestMethodType" mixed="true">
		<ns1:sequence>
			<ns1:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
		</ns1:sequence>
		<ns1:attribute name="Algorithm" type="ns1:anyURI" use="required"/>
	</ns1:complexType>
	<ns1:element name="DigestValue" type="DigestValueType"/>
	<ns1:simpleType name="DigestValueType">
		<ns1:restriction base="ns1:base64Binary"/>
	</ns1:simpleType>
	<!-- End SignedInfo -->
	<!-- Start KeyInfo -->
	<ns1:element name="KeyInfo" type="KeyInfoType"/>
	<ns1:complexType name="KeyInfoType" mixed="true">
		<ns1:choice maxOccurs="unbounded">
			<ns1:element ref="KeyName"/>
			<ns1:element ref="KeyValue"/>
			<ns1:element ref="RetrievalMethod"/>
			<ns1:element ref="X509Data"/>
			<ns1:element ref="PGPData"/>
			<ns1:element ref="SPKIData"/>
			<ns1:element ref="MgmtData"/>
			<ns1:any namespace="##other" processContents="lax"/>
			<!-- (1,1) elements from (0,unbounded) namespaces -->
		</ns1:choice>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
	</ns1:complexType>
	<ns1:element name="KeyName" type="ns1:string"/>
	<ns1:element name="MgmtData" type="ns1:string"/>
	<ns1:element name="KeyValue" type="KeyValueType"/>
	<ns1:complexType name="KeyValueType" mixed="true">
		<ns1:choice>
			<ns1:element ref="DSAKeyValue"/>
			<ns1:element ref="RSAKeyValue"/>
			<ns1:any namespace="##other" processContents="lax"/>
		</ns1:choice>
	</ns1:complexType>
	<ns1:element name="RetrievalMethod" type="RetrievalMethodType"/>
	<ns1:complexType name="RetrievalMethodType">
		<ns1:sequence>
			<ns1:element ref="Transforms" minOccurs="0"/>
		</ns1:sequence>
		<ns1:attribute name="URI" type="ns1:anyURI"/>
		<ns1:attribute name="Type" type="ns1:anyURI" use="optional"/>
	</ns1:complexType>
	<!-- Start X509Data -->
	<ns1:element name="X509Data" type="X509DataType"/>
	<ns1:complexType name="X509DataType">
		<ns1:sequence maxOccurs="unbounded">
			<ns1:choice>
				<ns1:element name="X509IssuerSerial" type="X509IssuerSerialType"/>
				<ns1:element name="X509SKI" type="ns1:base64Binary"/>
				<ns1:element name="X509SubjectName" type="ns1:string"/>
				<ns1:element name="X509Certificate" type="ns1:base64Binary"/>
				<ns1:element name="X509CRL" type="ns1:base64Binary"/>
				<ns1:any namespace="##other" processContents="lax"/>
			</ns1:choice>
		</ns1:sequence>
	</ns1:complexType>
	<ns1:complexType name="X509IssuerSerialType">
		<ns1:sequence>
			<ns1:element name="X509IssuerName" type="ns1:string"/>
			<ns1:element name="X509SerialNumber" type="ns1:integer"/>
		</ns1:sequence>
	</ns1:complexType>
	<!-- End X509Data -->
	<!-- Begin PGPData -->
	<ns1:element name="PGPData" type="PGPDataType"/>
	<ns1:complexType name="PGPDataType">
		<ns1:choice>
			<ns1:sequence>
				<ns1:element name="PGPKeyID" type="ns1:base64Binary"/>
				<ns1:element name="PGPKeyPacket" type="ns1:base64Binary" minOccurs="0"/>
				<ns1:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
			</ns1:sequence>
			<ns1:sequence>
				<ns1:element name="PGPKeyPacket" type="ns1:base64Binary"/>
				<ns1:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
			</ns1:sequence>
		</ns1:choice>
	</ns1:complexType>
	<!-- End PGPData -->
	<!-- Begin SPKIData -->
	<ns1:element name="SPKIData" type="SPKIDataType"/>
	<ns1:complexType name="SPKIDataType">
		<ns1:sequence maxOccurs="unbounded">
			<ns1:element name="SPKISexp" type="ns1:base64Binary"/>
			<ns1:any namespace="##other" processContents="lax" minOccurs="0"/>
		</ns1:sequence>
	</ns1:complexType>
	<!-- End SPKIData -->
	<!-- End KeyInfo -->
	<!-- Start Object (Manifest, SignatureProperty) -->
	<ns1:element name="Object" type="ObjectType"/>
	<ns1:complexType name="ObjectType" mixed="true">
		<ns1:sequence minOccurs="0" maxOccurs="unbounded">
			<ns1:any namespace="##any" processContents="lax"/>
		</ns1:sequence>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
		<ns1:attribute name="MimeType" type="ns1:string" use="optional"/>
		<ns1:attribute name="Encoding" type="ns1:anyURI" use="optional"/>
		<!-- add a grep facet -->
	</ns1:complexType>
	<ns1:element name="Manifest" type="ManifestType"/>
	<ns1:complexType name="ManifestType">
		<ns1:sequence>
			<ns1:element ref="Reference" maxOccurs="unbounded"/>
		</ns1:sequence>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
	</ns1:complexType>
	<ns1:element name="SignatureProperties" type="SignaturePropertiesType"/>
	<ns1:complexType name="SignaturePropertiesType">
		<ns1:sequence>
			<ns1:element ref="SignatureProperty" maxOccurs="unbounded"/>
		</ns1:sequence>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
	</ns1:complexType>
	<ns1:element name="SignatureProperty" type="SignaturePropertyType"/>
	<ns1:complexType name="SignaturePropertyType" mixed="true">
		<ns1:choice maxOccurs="unbounded">
			<ns1:any namespace="##other" processContents="lax"/>
			<!-- (1,1) elements from (1,unbounded) namespaces -->
		</ns1:choice>
		<ns1:attribute name="Target" type="ns1:anyURI" use="required"/>
		<ns1:attribute name="Id" type="ns1:ID" use="optional"/>
	</ns1:complexType>
	<!-- End Object (Manifest, SignatureProperty) -->
	<!-- Start Algorithm Parameters -->
	<ns1:simpleType name="HMACOutputLengthType">
		<ns1:restriction base="ns1:integer"/>
	</ns1:simpleType>
	<!-- Start KeyValue Element-types -->
	<ns1:element name="DSAKeyValue" type="DSAKeyValueType"/>
	<ns1:complexType name="DSAKeyValueType">
		<ns1:sequence>
			<ns1:sequence minOccurs="0">
				<ns1:element name="P" type="CryptoBinary"/>
				<ns1:element name="Q" type="CryptoBinary"/>
			</ns1:sequence>
			<ns1:element name="G" type="CryptoBinary" minOccurs="0"/>
			<ns1:element name="Y" type="CryptoBinary"/>
			<ns1:element name="J" type="CryptoBinary" minOccurs="0"/>
			<ns1:sequence minOccurs="0">
				<ns1:element name="Seed" type="CryptoBinary"/>
				<ns1:element name="PgenCounter" type="CryptoBinary"/>
			</ns1:sequence>
		</ns1:sequence>
	</ns1:complexType>
	<ns1:element name="RSAKeyValue" type="RSAKeyValueType"/>
	<ns1:complexType name="RSAKeyValueType">
		<ns1:sequence>
			<ns1:element name="Modulus" type="CryptoBinary"/>
			<ns1:element name="Exponent" type="CryptoBinary"/>
		</ns1:sequence>
	</ns1:complexType>
	<!-- End KeyValue Element-types -->
	<!-- End Signature -->
</ns1:schema>

Add API to write to stream rather than to files

I prefer doing schema manipulations in memory until required to write to files. Since this potential may write out to multiple files, it could be added as a configuration item as:

public interface ICodeWriter
{
  public void Write(GeneratorConfiguration config, string namespace, CodeCompileUnit cu);
}

This way, you can have implementations that write out to files or to streams.

Disable prefixing of type name with parent type name

For a schema that looks like the following:

<?xml version="1.0" encoding="utf-16"?>
<xsd:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified">
  <xs:element name="MachineList">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="Machine">
          <xs:complexType>
            <xs:sequence>
              <xs:choice maxOccurs="unbounded">
                ...
              </xs:choice>
            </xs:sequence>
            <xs:attribute name="Name" type="xs:string" use="required" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xsd:schema>

The generated code contains a class corresponding to our <xs:element maxOccurs="unbounded" name="Machine"> element with the name: public partial class MachineListMachine.

Is it possible to disable this prefixing of the type name with the parent type's name (or otherwise customize it)? I'd like the class to instead simply be named public partial class Machine.

Release is missing binaries

It would be nice if the releases would also include the .exe and whatever .dll's necessary in order to run.

Imported files are not processed correctly

I have several schemas that use shared types defined in another schema. I can generate these with a single run of xsd.exe, but it doesn't provide some of the features I need.

> xsd -c -f shared.xsd main1.xsd main2.xsd
Writing file 'shared_main1_main2.cs'.

When I try the same thing with XmlSchemaClassGenerator, I get a variety of exceptions. At first I thought it was a problem with two xsd files importing the same shared file, but then I tried it with just one of the main files. The exception I get depends on which file I specify first:

>XmlSchemaClassGenerator.Console.exe shared.xsd main1.xsd
Unhandled Exception: System.Exception: Namespace main1 not provided through map or generator.
   at XmlSchemaClassGenerator.Generator.BuildNamespace(Uri source, String xmlNamespace)
   at XmlSchemaClassGenerator.Generator.CreateNamespaceModel(Uri source, XmlQualifiedName qualifiedName)
   at XmlSchemaClassGenerator.Generator.CreateTypeModel(Uri source, XmlSchemaAnnotated type, XmlQualifiedName qualifiedName)
   at XmlSchemaClassGenerator.Generator.BuildModel()
   at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files)
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args)


>XmlSchemaClassGenerator.Console.exe main1.xsd shared.xsd
Unhandled Exception: System.Xml.Schema.XmlSchemaException: The complexType 'Shared:sharedType' has already been declared.
   at System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
   at System.Xml.Schema.BaseProcessor.AddToTable(XmlSchemaObjectTable table, XmlQualifiedName qname, XmlSchemaObject item)
   at System.Xml.Schema.Compiler.Prepare(XmlSchema schema, Boolean cleanup)
   at System.Xml.Schema.XmlSchemaSet.Compile()
   at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files)
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args)

shared.xsd
main1.xsd
main2.xsd

xs:dateTime issue / question

Hi Mganss

I have the following example ....

from XSD:

<xs:element name="DateOfBirth" type="xs:dateTime" nillable="true">
  <xs:annotation>
    <xs:documentation>The date the person was born. The time part of this attribute should be 0. </xs:documentation>
  </xs:annotation>
</xs:element>

from generated C# class:

/// <summary>
/// <para>The date the person was born. The time part of this attribute should be 0. </para>
/// </summary>
[System.Xml.Serialization.XmlElementAttribute("DateOfBirth", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, DataType="dateTime")]
public System.DateTime DateOfBirth { get; set; }

Question:

Shouldn't:

public System.DateTime DateOfBirth { get; set; }

Be like this ?:

public System.DateTime? DateOfBirth { get; set; }

Reason for asking is when try to serialize it back it fails.
But when I add the "?" it works fine.
Also for information I use the XmlSerializer from namespace : System.Xml.Serialization

Thanks

//Regards Niklas

Date types are not serialized correctly

I've started using the generator to replace xsd.exe, since I use a large base schema which I don't want duplicated in all sub types. But I've noticed a difference in generated code.

Elements of the following type:

<xs:simpleType name="LDT_Datum">
	<xs:annotation>
		<xs:documentation>Datum</xs:documentation>
	</xs:annotation>
	<xs:restriction base="xs:date">
		<xs:pattern value="[^:Z]*"/>
	</xs:restriction>
</xs:simpleType>

Get generated as:

/// <summary>
/// <para>Datum</para>
/// <para>Datum</para>
/// <para xml:lang="en">Pattern: [^:Z]*.</para>
/// </summary>
[System.ComponentModel.DataAnnotations.RegularExpressionAttribute("[^:Z]*")]
[System.Xml.Serialization.XmlElementAttribute("Datum", Namespace="http://www.istandaarden.nl/iwlz/1_2/basisschema/schema/1_2")]
public System.DateTime Datum { get; set; }

And xsd.exe adds the following to XmlElementAttribute: DataType = "date"

This difference results in wrongly generated XML, since the time gets generated also.

Namespace mapping not working

It appears that you always get a generated .net namspace even when you call the program with the -n parameter. I have been able to deduce it to the following code:

    public bool TryGetValue(NamespaceKey key, out string value)
    {
        if (InternalDictionary.TryGetValue(key, out value))
            return true;
        if (!TryGenerateNamespace(key, out value))
            return false;
        InternalDictionary.Add(key, value);
        return true;
    }

I don't believe that InternalDictionary.TryGetValue will ever succeed here because the NamespaceKey object passed through the "key" argument is a different instance from the one already in the collection. I have also found that the NamespaceKey:Source is populated with the full path to the xsd file in the "key" object. However since including the filename with the -n command line parameter appears to be optional, the NamespaceKey:Source properties of the two instances will not match. This will also occur if you do not specify the full path to the filename. I believe what you meant to do here is compare the NameSpaceKey:XmlSchemaNamespace properties for a match.

Add the possibility to specify an output filename

It would be handy to specify the output filename, currently it's only possible to select the output folder. (I guess since you can have more then 1 file). But when you do have one file, it would be great if you could specify it.

This is meant for the console version and the dotnettool version.

Class name collisions and loss of schema

Encountered an issue with the class generation using a large set of schema I was given. Here is a part of the schema that causes this problem:

<xs:element name="CreateSessionResponse">
	<xs:complexType>
		<xs:sequence>
			<xs:element maxOccurs="1" minOccurs="0" name="CreateSessionResult" type="tns:CreateSessionResponse"/>
		</xs:sequence>
	</xs:complexType>
</xs:element>
<xs:complexType name="CreateSessionResponse">
	<xs:complexContent mixed="false">
		<xs:extension base="tns:OutputResponse">
			<xs:sequence>
				<xs:element maxOccurs="1" minOccurs="0" name="output" type="tns:CreateSessionResult"/>
			</xs:sequence>
		</xs:extension>
	</xs:complexContent>
</xs:complexType>

There are two nodes that both get constructed into classes with the same name.

This is what is generated for the above xml. You can see two XmlTypeAttributes listed; once for each node, but only one class gets actually written out. Leaving me with an incomplete implementation.

    [System.CodeDom.Compiler.GeneratedCodeAttribute("XmlSchemaClassGenerator", "2.0.85.0")]
    [System.Xml.Serialization.XmlTypeAttribute("CreateSessionResponse", Namespace="http://example.com/service/v1")]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.Xml.Serialization.XmlRootAttribute("CreateSessionResponse", Namespace="http://example.com/service/v1")]
    public partial class CreateSessionResponse : OutputResponse
    {
        
        [System.Xml.Serialization.XmlElementAttribute("output", Namespace="http://example.com/service/v1")]
        public CreateSessionResult output { get; set; }
    }

I am unable to change the source schema and do not believe it to be an issue with the schema as it is generated. Also from having used svcutil on this schema, I know that it will resolve class name collisions by appending incremental numbers to the end of the duplicates. Personally, I do not like the incremental numbers but it does solve the issue.

What are your thoughts on this?

Here is what svcutil generates for comparison

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
    [System.ServiceModel.MessageContractAttribute(WrapperName="CreateSessionResponse", WrapperNamespace="http://example.com/service/v1", IsWrapped=true)]
    public partial class CreateSessionResponse1
    {

        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://example.com/service/v1", Order=0)]
        public ExampleService.CreateSessionResponse CreateSessionResult;

        public CreateSessionResponse1()
        {
        }

        public CreateSessionResponse1(ExampleService.CreateSessionResponse CreateSessionResult)
        {
            this.CreateSessionResult = CreateSessionResult;
        }
    }

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.com/service/v1")]
    public partial class CreateSessionResponse : OutputResponse
    {

        private CreateSessionResult outputField;

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Order=0)]
        public CreateSessionResult output
        {
            get
            {
                return this.outputField;
            }
            set
            {
                this.outputField = value;
            }
        }
    }

Index was outside the bounds of the array.

I'm trying to use this project with the following xsd:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="BaseCondition">
      <xs:attribute type="xs:string" name="name" use="optional"/>
      <xs:attribute type="xs:string" name="value" use="optional"/>
  </xs:complexType>
  <xs:complexType name="BaseGroup">
    <xs:choice minOccurs="1" maxOccurs="unbounded">
      <xs:element name="EXISTS" type="BaseCondition" minOccurs="0" />
      <xs:element name="LT" type="BaseCondition" minOccurs="0"/>
      <xs:element name="LTE" type="BaseCondition" minOccurs="0"/>
      <xs:element name="GT" type="BaseCondition" minOccurs="0"/>
      <xs:element name="GTE" type="BaseCondition" minOccurs="0"/>
      <xs:element name="EQ" type="BaseCondition" minOccurs="0"/>
      <xs:element name="NE" type="BaseCondition" minOccurs="0"/>
      <xs:element name="LIKE" type="BaseCondition" minOccurs="0"/>
      <xs:element name="NOTLIKE" type="BaseCondition" minOccurs="0"/>
      <xs:element name="IN" type="BaseCondition" minOccurs="0"/>
      <xs:element name="NOTIN" type="BaseCondition" minOccurs="0"/>
      <xs:element name="WITHIN" type="BaseCondition" minOccurs="0"/>
      <xs:element name="AND" type="BaseGroup" minOccurs="0"/>
      <xs:element name="OR" type="BaseGroup" minOccurs="0"/>
    </xs:choice>
  </xs:complexType>
  <xs:complexType name="Login">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:string" name="authenticationkey"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="Query">
    <xs:sequence>
      <xs:element name="FILTER" type="BaseGroup"/>
      <xs:element name="INCLUDE" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="objecttype"/>
    <xs:attribute type="xs:string" name="orderby"/>
  </xs:complexType>
  <xs:element name="REQUEST">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="LOGIN" type="Login"/>
        <xs:element name="QUERY" type="Query"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

and the following command line XmlSchemaClassGenerator.Console.exe --namespace=Test Trafikverket.xsd

but i get the following error:

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at XmlSchemaClassGenerator.Console.Program.ParseNamespace(String nsArg, String namespacePrefix)
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at XmlSchemaClassGenerator.EnumerableExtensions.ToNamespaceProvider(IEnumerable`1 items, GenerateNamespaceDelegate generate)
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args)

what am i doing wrong?

Error in trying to replace default collection type

What is the proper way to replace the collection type used in the generated code?

dotnet XmlSchemaClassGenerator.Console.dll *.xsd -o output -n http://www.iata.org/IATA/EDIST/2017.2=IATA -v -ct Systems.Collections.Generic.List

generates

Unhandled Exception: System.TypeLoadException: Could not load type 'Systems.Collections.Generic.List' from assembly 'XmlSchemaClassGenerator.Console, Version=2.0.82.0, Culture=neutral, PublicKeyToken=null'.
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
   at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
   at System.Type.GetType(String typeName, Boolean throwOnError)
   at XmlSchemaClassGenerator.Console.Program.<>c__DisplayClass0_0.<Main>b__13(String v) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator.Console\Program.cs:line 74
   at Mono.Options.Option.Invoke(OptionContext c) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator.Console\Mono.Options\Options.cs:line 616
   at Mono.Options.OptionSet.Parse(String argument, OptionContext c) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator.Console\Mono.Options\Options.cs:line 1160
   at Mono.Options.OptionSet.Parse(IEnumerable`1 arguments) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator.Console\Mono.Options\Options.cs:line 1060
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args) in C:\projects\xmlschemaclassgenerator\XmlSchemaClassGenerator.Console\Program.cs:line 82
E:\ndc```

TypeModel generates wrong XMLArray Namespace

I use Elements from other namespaces and include those in my type using the ref-Attribute.
The Daten Element is in the namespace http://nota-game.azurewebsites.net/schema/nota

  <element name="Daten">
    <complexType>
      <sequence>
        <element minOccurs="0" name="Pfade">
          <complexType>
             ....
          </complexType>
        </element>
        <element ref="lebewesen:Lebewesene"/>
        ...
      </sequence>
    </complexType>
  </element>

The generated Property looks like:

        /// <summary>
        /// </summary>
        [System.Xml.Serialization.XmlArrayAttribute("Lebewesene", Namespace="http://nota-game.azurewebsites.net/schema/nota")]
        [System.Xml.Serialization.XmlArrayItemAttribute("Lebewesen", Namespace="http://nota-game.azurewebsites.net/schema/lebewesen")]
        public System.Collections.ObjectModel.Collection<Nota.CharacterGenerator.CoreData.Lebewesen.LebeweseneLebewesen> Lebewesene { get {...} }

However the Namespace of the XmlArrayAttribute should be http://nota-game.azurewebsites.net/schema/lebewesen.

The TypeModel sets the namespace to the Owning type if Form equals XmlSchemaForm.Qualified. However if the element is not delcread at this position but referenced from another Namespace it should be the namespace of the referenced element. In your code this seems to be XmlNamespace.

I tested to change the order of the checks in TypeModel.
First Checking if XmlNamespace != null and if this fails checking if Form == XmlSchemaForm.Qualified.

This worked for my so far, but I'm not sure about the side effects. That's why I haven't created an pull request yet.

This are the changes.

Support Enums with different spelled values

The tool works great but has one little issue when it comes to enums with different spelled values (for example usefull for User-Inputs).
Example

<xsd:simpleType name="Gender">
	<xsd:restriction base="xsd:string">
		<xsd:enumeration value="male"/>
		<xsd:enumeration value="female"/>
		<xsd:enumeration value="Male"/>
		<xsd:enumeration value="Female"/>
	</xsd:restriction>
</xsd:simpleType>

This lead to an not valid Enum, because the Member "Male" and "Female" would be generated twice.

API out of sync with README

The README has a snippet referring to GenerateNamespaceName and NamespaceMapping, which I'm assuming are supposed to be used for mapping namespaces from the XML schema into namespaces in the generated C#. These properties no longer seem to be a part of the Generator class. Could the README be updated to show how to properly initialize a Generator?

xs:time is serialized as string

schema properties with datatype xs:time are serialized as string
xsd.exe serializes these properties as System.DateTime

would be nice to have an option to supply xs:time datatype the same way that integers are being handled.

XmlSchemaException when trying to use my XSD

Hi, I just tried your tool but I have some odd behavior.

I try to create code from this xsd.

But this fails with:

Unbehandelte Ausnahme: System.Xml.Schema.XmlSchemaException: Die Identitätseinschränkung 'http://nota-game.azurewebsites.net/schema/nota:BesonderheitPK' wurde bereits deklariert.
   bei System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
   bei System.Xml.Schema.BaseProcessor.SendValidationEvent(XmlSchemaException e, XmlSeverityType severity)
   bei System.Xml.Schema.Preprocessor.PreprocessIdentityConstraint(XmlSchemaIdentityConstraint constraint)
   bei System.Xml.Schema.Preprocessor.PreprocessElementContent(XmlSchemaElement element)
   bei System.Xml.Schema.Preprocessor.PreprocessElement(XmlSchemaElement element)
   bei System.Xml.Schema.Preprocessor.Preprocess(XmlSchema schema, String targetNamespace, ArrayList imports)
   bei System.Xml.Schema.Preprocessor.Execute(XmlSchema schema, String targetNamespace, Boolean loadExternals)
   bei System.Xml.Schema.XmlSchemaSet.PreprocessSchema(XmlSchema& schema, String targetNamespace)
   bei System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace, XmlSchema schema)
   bei System.Xml.Schema.XmlSchemaSet.Add(XmlSchema schema)
   bei XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files) in C:\Users\patri\Source\Repos\XmlSchemaClassGenerator\XmlSchemaClassGenerator\Generator.cs:Zeile 185.
   bei XmlSchemaClassGenerator.Console.Program.Main(String[] args) in C:\Users\patri\Source\Repos\XmlSchemaClassGenerator\XmlSchemaClassGenerator.Console\Program.cs:Zeile 133.

I thought that the tool maybe mix up my local copy of the xsd and also importing it from the website, because it has a schemalocation. So I modified the code that it also can use URLs additionally to files. And well it helped, code generation worked. But then I testet the "fix" on the console the exception was there again.

It works most of the time with the debugger attached, but running from command line always results in the exception.

Maybe it has something todo with a circular dependency of the xsd files. I think this was the reasen the xsd.exe got a stackoverflowexception.

Output file selection does not work.

Selecting the output file by using the '|' char after the xml schema name does not appear to work.

The current code causes a Namespacekey to be added to the NamespaceProvider.InternalDictionary dictionary with the source field set to the file name. (see line 92 of console program.cs).

When Generator.BuildNamespace is called, the source field of the NamespaceKey is set to the Uri of the source xsd file, and NamespaceProvider.FindNamespace fails to find a match. (see line 235 of Generator.cs)

The following are the command line args I used to get this error.
XmlSchemaClassGenerator ElmSchemaSource\Types.xsd -o=ElmSchemaGenerated -n="urn:hl7-org:elm-types:r1|Types.cs"="Applicadia2.Import.CQL.ElmModel"

Use dependency injection to manage services

While making a few updates to the project, it seems like there are a number of services that need to be passed around and are all updated via the Generator as well as GeneratorConfiguration via some linked properties. Already with the number of services available, this system is getting unwieldy with entries in both Generator and GeneratorConfiguration. I think it would be much simpler to swap this out to use a DI container to control this and the creation of dependencies. This would simplify using it in other applications where services could more easily be swapped out as well as depend on each other. I'd be happy to submit a PR, but wanted to solicit feedback on the idea before doing the work.

extension and group mapping

It would be nice to be able to map the extension and grouping features from XSD onto the generated classes. I have solved it using inheritance for extension and interfaces for groups. I'm not sure if this works in general but it worked for my usecase.

I needed this feature for mapping the old IS24 XML format to the new one, to fill the properties interface-wise and not copy-paste all the mapping for each class. Would be great to have it in your version if you see it as generalizable.

Here an example of how my generated RealEstates class looks like:
https://raw.githubusercontent.com/Falco20019/IS24RestApi/master/IS24RestApi/generated/IS24RestApi.Offer.RealEstates.cs

I have not published my fork yet since I just hacked the feature quick & dirty into your nice code and since it doesn't merge with your new additions. If you think this could be something interesting, I try to clean it up and create a pull request.

Fixed value not initialized

I have a XSD containing following entry:
<xs:attribute name="version" type="xs:normalizedString" use="required" fixed="0500"/>

The xsd.exe initializes the value in the constructor with 0500, so that the user does not have to deal with it. It would be great, if you could add this too!

This is the patch I used to achieve a similar code generation. You might have to check if it's wanted that the FixedValue is used as DefaultValue in cases where the attribute is optional. The xsd.exe does not check this and always uses the FixedValue when no DefaultValue is given.

 XmlSchemaClassGenerator/Generator.cs | 2 ++
 XmlSchemaClassGenerator/TypeModel.cs | 9 +++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git XmlSchemaClassGenerator/Generator.cs XmlSchemaClassGenerator/Generator.cs
index 284fb1b..04fce92 100644
--- XmlSchemaClassGenerator/Generator.cs
+++ XmlSchemaClassGenerator/Generator.cs
@@ -708,6 +708,7 @@ namespace XmlSchemaClassGenerator
                             IsAttribute = true,
                             IsNullable = attribute.Use != XmlSchemaUse.Required,
                             DefaultValue = attribute.DefaultValue,
+                            FixedValue = attribute.FixedValue,
                             Form = attribute.Form == XmlSchemaForm.None ? attribute.GetSchema().AttributeFormDefault : attribute.Form,
                             XmlNamespace = attribute.QualifiedName.Namespace != "" && attribute.QualifiedName.Namespace != typeModel.XmlSchemaName.Namespace ? attribute.QualifiedName.Namespace : null,
                         };
@@ -780,6 +781,7 @@ namespace XmlSchemaClassGenerator
                         IsNullable = item.MinOccurs < 1.0m,
                         IsCollection = item.MaxOccurs > 1.0m || particle.MaxOccurs > 1.0m, // http://msdn.microsoft.com/en-us/library/vstudio/d3hx2s7e(v=vs.100).aspx
                         DefaultValue = element.DefaultValue,
+                        FixedValue = element.FixedValue,
                         Form = element.Form == XmlSchemaForm.None ? element.GetSchema().ElementFormDefault : element.Form,
                         XmlNamespace = element.QualifiedName.Namespace != "" && element.QualifiedName.Namespace != typeModel.XmlSchemaName.Namespace ? element.QualifiedName.Namespace : null,
                     };
diff --git XmlSchemaClassGenerator/TypeModel.cs XmlSchemaClassGenerator/TypeModel.cs
index 12bb39b..163fc5f 100644
--- XmlSchemaClassGenerator/TypeModel.cs
+++ XmlSchemaClassGenerator/TypeModel.cs
@@ -402,6 +402,7 @@ namespace XmlSchemaClassGenerator
         public bool IsNillable { get; set; }
         public bool IsCollection { get; set; }
         public string DefaultValue { get; set; }
+        public string FixedValue { get; set; }
         public XmlSchemaForm Form { get; set; }
         public string XmlNamespace { get; set; }
         public List<DocumentationModel> Documentation { get; private set; }
@@ -612,7 +613,7 @@ namespace XmlSchemaClassGenerator
             var typeReference = TypeReference;
             var simpleType = propertyType as SimpleModel;

-            var requiresBackingField = withDataBinding || DefaultValue != null || IsCollection || isArray;
+            var requiresBackingField = withDataBinding || DefaultValue != null || FixedValue != null || IsCollection || isArray;
             var backingField = new CodeMemberField(typeReference, OwningType.GetUniqueFieldName(this))
             {
                 Attributes = MemberAttributes.Private
@@ -626,7 +627,7 @@ namespace XmlSchemaClassGenerator
                 typeDeclaration.Members.Add(backingField);
             }

-            if (DefaultValue == null)
+            if (DefaultValue == null && FixedValue == null)
             {
                 var propertyName = isNullableValueType && Configuration.GenerateNullables ? Name + "Value" : Name;
                 member = new CodeMemberField(typeReference, propertyName);
@@ -645,13 +646,13 @@ namespace XmlSchemaClassGenerator
             }
             else
             {
-                var defaultValueExpression = propertyType.GetDefaultValueFor(DefaultValue);
+                var defaultValueExpression = propertyType.GetDefaultValueFor(DefaultValue ?? FixedValue);
                 backingField.InitExpression = defaultValueExpression;

                 member = new CodeMemberField(typeReference, Name);
                 member.Name += GetAccessors(member.Name, backingField.Name, propertyType.GetPropertyValueTypeCode(), false, withDataBinding);

-                if (IsNullable)
+                if (DefaultValue != null && IsNullable)
                 {
                     if (!(defaultValueExpression is CodeObjectCreateExpression))
                     {

Generated code may have mixed line endings

Not sure if this is a Git thing, or not, but because in my local copy of the Git repository TypeModel.cs is using UNIX line endings, when code is generated, you end up with a file with mixed line endings (eg. most are using Windows CRLF, but those that come from the GetAccessors() method may use the the Unix endings.

It is probably better to be explicit about what line endings are generated, rather than relying on what ever happens to be embedded in TypeModel.cs

How do you disable the interface generation?

I tried

dotnet XmlSchemaClassGenerator.Console.dll *.xsd -o output -n http://www.iata.org/IATA/EDIST/2017.2=IATA -n==XmlSchema -v -ct System.Collections.Generic.List`1 -t false

dotnet XmlSchemaClassGenerator.Console.dll *.xsd -o output -n http://www.iata.org/IATA/EDIST/2017.2=IATA -n==XmlSchema -v -ct System.Collections.Generic.List`1 -t false

dotnet XmlSchemaClassGenerator.Console.dll *.xsd -o output -n http://www.iata.org/IATA/EDIST/2017.2=IATA -n==XmlSchema -v -ct System.Collections.Generic.List`1 -t 0

At this moment I am getting compilation error related to interface such as

Severity	Code	Description	Project	File	Line	Suppression State
Error	CS0738	'ServiceListRS' does not implement interface member 'IIATA_PayloadStdAttributes.TransactionStatusCode'. 'ServiceListRS.TransactionStatusCode' cannot implement 'IIATA_PayloadStdAttributes.TransactionStatusCode' because it does not have the matching return type of 'IIATA_PayloadStdAttributesTransactionStatusCode'.	NDC.Xml	E:\NDC\NDC.Xml\IATA.cs	115130	Active
Error	CS0738	'ServiceListRS' does not implement interface member 'IIATA_PayloadStdAttributes.Target'. 'ServiceListRS.Target' cannot implement 'IIATA_PayloadStdAttributes.Target' because it does not have the matching return type of 'IIATA_PayloadStdAttributesTarget'.	NDC.Xml	E:\NDC\NDC.Xml\IATA.cs	115130	Active

My thinking is that without interface generation, these errors would go away.

Add API to supply XmlSchemaSet directly rather than just files

I'm having trouble with a multifile schema when passing it files as the XmlResolver isn't set correctly on the schema set. I'd prefer to just load up my schemas myself to ensure everything is resolved correctly. I took a look at the way this is set up and it would be difficult as-is as the XmlSchemaSet is a read only item that is just added to (this design also makes reuse of the generator difficult, but that's probably a different issue).

My suggestion would be to add a configuration item that was a "SchemaProvider":

public interface ISchemaSetProvider
{
  XmlSchemaSet GetSchemaSet(GeneratorConfiguration config);
}

with the default implementation loading the schemas as is currently done.

Using '|' to map XML namespace to input file fails

Summary

I am using using XmlSchemaClassGenerator-beta version 2.0.106.

Following the documentation, I am trying to use the | character to delimit the XML namespace and the corresponding file. In my example this namepace/file is a dependency of the primary xsd document. This fails with an System.Xml.Schema.XmlSchemaException claiming the dependency type in the reference namespace/file is not declared.

Minimal Reproducible Example:

name.xsd defines a FullName element representing a persons name. contacts.xsd defines an element 'Contacts' element which is list of FullName elements defined in the dependency name.xsd schema.

Command issued:
.\dotnet-xscgen.exe -n "http://example.com/name|name.xsd=Example.Name" -n "http://example.com/contacts=Example.Contacts" contacts.xsd

File name.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://example.com/name"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="http://example.com/name" elementFormDefault="qualified">

  <xs:complexType name="FullName">
    <xs:sequence>
      <xs:element type="xs:string" name="GivenName" minOccurs="1" maxOccurs="1"/>
      <xs:element type="xs:string" name="FamilyName" minOccurs="1" maxOccurs="1"/>
    </xs:sequence>
  </xs:complexType>
  
  <xs:element type="FullName" name="FullName"></xs:element>
</xs:schema>

File contacts.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://example.com/contacts"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:name="http://example.com/name"
           xmlns="http://example.com/contacts" elementFormDefault="qualified">

  <xs:complexType name="Contacts">
    <xs:sequence>
      <xs:element type="name:FullName" name="Contact" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  
  <xs:element type="Contacts" name="Contacts"></xs:element>
</xs:schema>

Output:

Unhandled Exception: System.Xml.Schema.XmlSchemaException: Type 'http://example.com/name:FullName' is not declared.
   at System.Xml.Schema.XmlSchemaSet.InternalValidationCallback(Object sender, ValidationEventArgs e)
   at System.Xml.Schema.Compiler.CompileElement(XmlSchemaElement xe)
   at System.Xml.Schema.Compiler.CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle)
   at System.Xml.Schema.Compiler.CompileParticleElements(XmlSchemaComplexType complexType, XmlSchemaParticle particle)
   at System.Xml.Schema.Compiler.CompileComplexTypeElements(XmlSchemaComplexType complexType)
   at System.Xml.Schema.Compiler.Compile()
   at System.Xml.Schema.Compiler.Execute(XmlSchemaSet schemaSet, SchemaInfo schemaCompiledInfo)
   at System.Xml.Schema.XmlSchemaSet.Compile()
   at XmlSchemaClassGenerator.Generator.Generate(IEnumerable`1 files)
   at XmlSchemaClassGenerator.Console.Program.Main(String[] args)

Missing (public) setter when dealing with Lists and Arrays.

It seems Arrays and Lists are generating no setters.
When I try to deserialize XML with Arrays and Lists, the objects are missing in the C# Model.

TypeClass.cs in Line 504:
var isPrivateSetter = IsCollection || isArray;
When I change it to var isPrivateSetter = false; deserialization works fine, because setters are generated.

Add API that provides opportunity to customise members

As a consumer of the XmlSchemaClassGenerator library It would be great to have a way to inspect each member as they're being generated and have an opportunity to modify the member as required.

eg. I'd like to add additional attributes to each generated member.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.