diff --git a/XmlSchemaClassGenerator.SourceGenerator.Tests/Samples/simple_schema.xsd b/XmlSchemaClassGenerator.SourceGenerator.Tests/Samples/simple_schema.xsd
new file mode 100644
index 00000000..c89fcff4
--- /dev/null
+++ b/XmlSchemaClassGenerator.SourceGenerator.Tests/Samples/simple_schema.xsd
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/XmlSchemaClassGenerator.SourceGenerator.Tests/SimpleSchemaTests.cs b/XmlSchemaClassGenerator.SourceGenerator.Tests/SimpleSchemaTests.cs
new file mode 100644
index 00000000..ff18e144
--- /dev/null
+++ b/XmlSchemaClassGenerator.SourceGenerator.Tests/SimpleSchemaTests.cs
@@ -0,0 +1,21 @@
+using Xunit;
+
+namespace XmlSchemaClassGenerator.SourceGenerator.Tests
+{
+ public class SimpleSchemaTests
+ {
+ [Fact]
+ public void Compiles()
+ {
+ new Sample.Generated.MyRootElement
+ {
+ Child1 = true,
+ Child2 = "foo",
+ ComplexChild1 = new Sample.Generated.MyRootElementComplexChild1
+ {
+ Child11 = null
+ }
+ };
+ }
+ }
+}
diff --git a/XmlSchemaClassGenerator.SourceGenerator.Tests/XmlSchemaClassGenerator.SourceGenerator.Tests.csproj b/XmlSchemaClassGenerator.SourceGenerator.Tests/XmlSchemaClassGenerator.SourceGenerator.Tests.csproj
new file mode 100644
index 00000000..c2dd5eba
--- /dev/null
+++ b/XmlSchemaClassGenerator.SourceGenerator.Tests/XmlSchemaClassGenerator.SourceGenerator.Tests.csproj
@@ -0,0 +1,40 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/XmlSchemaClassGenerator.SourceGenerator/XmlSchemaClassGenerator.SourceGenerator.csproj b/XmlSchemaClassGenerator.SourceGenerator/XmlSchemaClassGenerator.SourceGenerator.csproj
new file mode 100644
index 00000000..5963eb31
--- /dev/null
+++ b/XmlSchemaClassGenerator.SourceGenerator/XmlSchemaClassGenerator.SourceGenerator.csproj
@@ -0,0 +1,74 @@
+
+
+
+ netstandard2.0
+ false
+ true
+
+ XmlSchemaClassGenerator.SourceGenerator
+ Sven Hübner
+ Source generator for POCOs from XSD schema files, based on XmlSchemaClassGenerator
+ xml;xsd;Schema;Source Generator;poco;XmlSchemaClassGenerator
+ https://github.com/mganss/XmlSchemaClassGenerator
+ Apache-2.0
+ git
+ git://github.com/mganss/XmlSchemaClassGenerator
+ XmlSchemaClassGenerator
+ true
+ true
+ true
+ snupkg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(GetTargetPathDependsOn);GetDependencyTargetPaths
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/XmlSchemaClassGenerator.SourceGenerator/XmlSchemaClassGenerator.SourceGenerator.props b/XmlSchemaClassGenerator.SourceGenerator/XmlSchemaClassGenerator.SourceGenerator.props
new file mode 100644
index 00000000..08b674a0
--- /dev/null
+++ b/XmlSchemaClassGenerator.SourceGenerator/XmlSchemaClassGenerator.SourceGenerator.props
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/XmlSchemaClassGenerator.SourceGenerator/XsdSourceGenerator.cs b/XmlSchemaClassGenerator.SourceGenerator/XsdSourceGenerator.cs
new file mode 100644
index 00000000..97db1721
--- /dev/null
+++ b/XmlSchemaClassGenerator.SourceGenerator/XsdSourceGenerator.cs
@@ -0,0 +1,171 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using System;
+using System.CodeDom;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.Schema;
+
+namespace XmlSchemaClassGenerator
+{
+ [Generator]
+ public class XsdSourceGenerator : ISourceGenerator
+ {
+ internal class MemoryOutputWriter : OutputWriter
+ {
+ private readonly bool separateFiles;
+ private readonly string schemaFileName;
+ private readonly string prefix;
+
+ public ICollection<(string Name, string Content)> Contents { get; private set; } = new List<(string, string)>();
+
+ public MemoryOutputWriter(bool separateFiles, string schemaFileName, string prefix)
+ {
+ this.separateFiles = separateFiles;
+ this.schemaFileName = schemaFileName;
+ this.prefix = prefix;
+ }
+
+ public override void Write(CodeNamespace cn)
+ {
+ var cu = new CodeCompileUnit();
+ cu.Namespaces.Add(cn);
+
+ if (separateFiles)
+ {
+ WriteSeparateFiles(cn);
+ }
+ else
+ {
+ using (var writer = new StringWriter())
+ {
+ Write(writer, cu);
+ Contents.Add(($"{this.prefix ?? string.Empty}{this.schemaFileName}.g.cs", writer.ToString()));
+ }
+ }
+ }
+
+ private void WriteSeparateFiles(CodeNamespace cn)
+ {
+ var validName = GetSanitizedName(cn.Name);
+ var ccu = new CodeCompileUnit();
+ var cns = new CodeNamespace(validName);
+
+ cns.Imports.AddRange(cn.Imports.Cast().ToArray());
+ cns.Comments.AddRange(cn.Comments);
+ ccu.Namespaces.Add(cns);
+
+ foreach (CodeTypeDeclaration ctd in cn.Types)
+ {
+ var contentName = ctd.Name;
+ cns.Types.Clear();
+ cns.Types.Add(ctd);
+ using (var writer = new StringWriter())
+ {
+ Write(writer, ccu);
+ Contents.Add(($"{this.prefix ?? string.Empty}{contentName}.g.cs", writer.ToString()));
+ }
+ }
+ }
+
+ static readonly Regex InvalidCharacters = new Regex($"[{string.Join("", Path.GetInvalidFileNameChars())}]", RegexOptions.Compiled);
+
+ private string GetSanitizedName(string name) => InvalidCharacters.Replace(name, "_");
+ }
+
+ public void Execute(GeneratorExecutionContext context)
+ {
+#if DEBUG
+ if (!Debugger.IsAttached)
+ {
+ // Debugger.Launch();
+ }
+#endif
+ var sources = GetConfigurations(context);
+
+ foreach (var source in sources)
+ {
+ var schemaStr = source.AdditionalText.GetText().ToString();
+ var stringReader = new StringReader(schemaStr);
+
+ var schemaSet = new XmlSchemaSet();
+ schemaSet.Add(null, XmlReader.Create(stringReader));
+
+ var generator = new Generator();
+ generator.NamespaceProvider.Add(new NamespaceKey(), source.Namespace);
+ generator.SeparateClasses = source.GenerateSeparateFiles;
+ MemoryOutputWriter memoryOutputWriter = new MemoryOutputWriter(
+ source.GenerateSeparateFiles,
+ Path.GetFileNameWithoutExtension(source.AdditionalText.Path),
+ source.Prefix);
+ generator.OutputWriter = memoryOutputWriter;
+ generator.Generate(schemaSet);
+
+ foreach (var (name, content) in memoryOutputWriter.Contents)
+ {
+ context.AddSource(name, content);
+ }
+ }
+ }
+
+ public void Initialize(GeneratorInitializationContext context)
+ {
+ // do nothing
+ }
+
+ static IEnumerable GetConfigurations(GeneratorExecutionContext context)
+ {
+ foreach (AdditionalText file in context.AdditionalFiles)
+ {
+ AnalyzerConfigOptions fileOptions = context.AnalyzerConfigOptions.GetOptions(file);
+ if (!fileOptions.TryGetValue("build_metadata.AdditionalFiles.xscgen_namespace", out var @namespace))
+ {
+ @namespace = "Generated";
+ }
+
+ if (!fileOptions.TryGetValue("build_metadata.AdditionalFiles.xscgen_prefix", out var prefix))
+ {
+ prefix = null;
+ }
+
+ bool generateSeparateFiles =
+ fileOptions.TryGetValue("build_metadata.AdditionalFiles.xscgen_separatefiles", out var generateSeparateFilesStr) &&
+ bool.TryParse(generateSeparateFilesStr, out var parsedGenerateSeparateFiles) &&
+ parsedGenerateSeparateFiles;
+
+ if (Path.GetExtension(file.Path).Equals(".xsd", StringComparison.OrdinalIgnoreCase))
+ {
+ yield return new GenerationSource(
+ file,
+ @namespace,
+ generateSeparateFiles,
+ prefix);
+ }
+ }
+ }
+
+ sealed class GenerationSource
+ {
+ public GenerationSource(
+ AdditionalText additionalText,
+ string @namespace,
+ bool generateSeparateFiles,
+ string prefix)
+ {
+ AdditionalText = additionalText;
+ Namespace = @namespace;
+ GenerateSeparateFiles = generateSeparateFiles;
+ Prefix = prefix;
+ }
+
+ public AdditionalText AdditionalText { get; }
+ public string Namespace { get; }
+ public bool GenerateSeparateFiles { get; }
+ public string Prefix { get; }
+ }
+ }
+}
diff --git a/XmlSchemaClassGenerator.sln b/XmlSchemaClassGenerator.sln
index 23fb93ad..9e36bfda 100644
--- a/XmlSchemaClassGenerator.sln
+++ b/XmlSchemaClassGenerator.sln
@@ -20,6 +20,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xscgen-proj", "xscgen-proj\xscgen-proj.csproj", "{2F20FF02-12AB-448B-BC78-DD76DD4C9E66}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlSchemaClassGenerator.SourceGenerator", "XmlSchemaClassGenerator.SourceGenerator\XmlSchemaClassGenerator.SourceGenerator.csproj", "{1A4760D7-7618-41E8-BC97-C68566B7A16C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlSchemaClassGenerator.SourceGenerator.Tests", "XmlSchemaClassGenerator.SourceGenerator.Tests\XmlSchemaClassGenerator.SourceGenerator.Tests.csproj", "{333F3108-2714-4706-ABA7-4298EFEBFCA7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -50,6 +54,14 @@ Global
{2F20FF02-12AB-448B-BC78-DD76DD4C9E66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F20FF02-12AB-448B-BC78-DD76DD4C9E66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F20FF02-12AB-448B-BC78-DD76DD4C9E66}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1A4760D7-7618-41E8-BC97-C68566B7A16C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A4760D7-7618-41E8-BC97-C68566B7A16C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1A4760D7-7618-41E8-BC97-C68566B7A16C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A4760D7-7618-41E8-BC97-C68566B7A16C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {333F3108-2714-4706-ABA7-4298EFEBFCA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {333F3108-2714-4706-ABA7-4298EFEBFCA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {333F3108-2714-4706-ABA7-4298EFEBFCA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {333F3108-2714-4706-ABA7-4298EFEBFCA7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj b/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj
index 233ee716..834ee80b 100644
--- a/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj
+++ b/XmlSchemaClassGenerator/XmlSchemaClassGenerator.csproj
@@ -48,7 +48,7 @@
-
+