From 457d8c8e6d498d5d20d8533f85fd18c3fd69d1da Mon Sep 17 00:00:00 2001 From: Marco Manfredini Date: Sat, 23 Nov 2024 22:13:33 +0100 Subject: [PATCH 1/4] Added command line option to force a URI scheme to use for the URLs resolved in XmlSchemaSet. --- README.md | 2 + XmlSchemaClassGenerator.Console/Program.cs | 6 ++- XmlSchemaClassGenerator/Generator.cs | 45 +++++++++++++++++-- .../GeneratorConfiguration.cs | 5 +++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a0914cc..946204f 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,8 @@ Options: --ns, --namingScheme use the specified naming scheme for class and property names (default is Pascal; can be: Direct, Pascal, Legacy) + --fu, --forceUriScheme=VALUE + force URI scheme when resolving Urls (default is none; can be: none, same, or any defined value for scheme, like https or http) For use from code use the [library NuGet package](https://www.nuget.org/packages/XmlSchemaClassGenerator-beta/): diff --git a/XmlSchemaClassGenerator.Console/Program.cs b/XmlSchemaClassGenerator.Console/Program.cs index a20584e..8cbb9fa 100644 --- a/XmlSchemaClassGenerator.Console/Program.cs +++ b/XmlSchemaClassGenerator.Console/Program.cs @@ -69,6 +69,8 @@ static int Main(string[] args) var serializeEmptyCollections = false; var allowDtdParse = false; NamingScheme? namingScheme = null; + var forceUriScheme = "none"; + var options = new OptionSet { { "h|help", "show this message and exit", v => showHelp = v != null }, @@ -176,7 +178,8 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l _ => NamingScheme.PascalCase, }; } - } + }, + { "fu|forceUriScheme=", "force URI scheme when resolving Urls (default is none; can be: none, same, or any defined value for scheme, like https or http)", v => forceUriScheme = v } }; var globsAndUris = options.Parse(args); @@ -266,6 +269,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l SeparateNamespaceHierarchy = separateNamespaceHierarchy, SerializeEmptyCollections = serializeEmptyCollections, AllowDtdParse = allowDtdParse, + ForceUriScheme = forceUriScheme }; if (namingScheme != null) diff --git a/XmlSchemaClassGenerator/Generator.cs b/XmlSchemaClassGenerator/Generator.cs index 36bfc26..17819bf 100644 --- a/XmlSchemaClassGenerator/Generator.cs +++ b/XmlSchemaClassGenerator/Generator.cs @@ -9,12 +9,52 @@ namespace XmlSchemaClassGenerator { + class NormalizingXmlResolver : XmlUrlResolver + { + // the Uri scheme to force on the resolved Uris + // "none" - do not change Uri scheme + // "same" - force the same Uri scheme as base Uri + // any other string becomes the new Uri scheme of the baseUri + private string forceUriScheme; + public NormalizingXmlResolver(string forceUriScheme) : base() + { + this.forceUriScheme=forceUriScheme; + } + public override Uri ResolveUri(Uri baseUri, string relativeUri) + { + Uri resolvedUri = base.ResolveUri(baseUri, relativeUri); + var r=NormalizeUri(baseUri, resolvedUri); + Console.WriteLine($"-- ResolveUri:from {baseUri} to {relativeUri}: {r}"); + return r; + } + private Uri NormalizeUri(Uri baseUri, Uri resolvedUri ) + { + var newScheme=forceUriScheme; + switch (forceUriScheme) + { + case "none": return resolvedUri; + case "same": + { + newScheme=baseUri.Scheme; + break; + } + } + UriBuilder builder = new UriBuilder(resolvedUri) { Scheme = newScheme, Port=-1}; + return builder.Uri; + } + } + public class Generator { private readonly GeneratorConfiguration _configuration = new(); public GeneratorConfiguration Configuration => _configuration; + public string ForceUriScheme + { + get { return _configuration.ForceUriScheme; } + set { _configuration.ForceUriScheme=value; } + } public NamespaceProvider NamespaceProvider { get { return _configuration.NamespaceProvider; } @@ -375,11 +415,10 @@ public void Generate(IEnumerable streams) public void Generate(IEnumerable readers) { - var set = new XmlSchemaSet(); - + var set = new XmlSchemaSet(); ValidationError = false; - set.XmlResolver = new XmlUrlResolver(); + set.XmlResolver = new NormalizingXmlResolver(ForceUriScheme); // XmlUrlResolver(); set.ValidationEventHandler += (s, e) => { var ex = e.Exception as Exception; diff --git a/XmlSchemaClassGenerator/GeneratorConfiguration.cs b/XmlSchemaClassGenerator/GeneratorConfiguration.cs index 78c5ffd..9d830f0 100644 --- a/XmlSchemaClassGenerator/GeneratorConfiguration.cs +++ b/XmlSchemaClassGenerator/GeneratorConfiguration.cs @@ -40,6 +40,7 @@ public GeneratorConfiguration() EnableUpaCheck = true; CommandLineArgumentsProvider = CommandLineArgumentsProvider.CreateFromEnvironment(); MergeRestrictionsWithBase = true; + ForceUriScheme = "none"; } public bool EnumAsString { get; set; } @@ -85,6 +86,10 @@ public GeneratorConfiguration() /// Generate attributes for nullable references to avoid compiler-warnings in .NET Core and Standard with nullable-checks. /// public bool EnableNullableReferenceAttributes { get; set; } + /// + /// Force Uri Scheme for resolved Urls in XmlSchemaSet + /// + public string ForceUriScheme { get; set; } private NamingScheme namingScheme; From c3c31f8a4ebe7c0cc3aed968955c5a525df813e1 Mon Sep 17 00:00:00 2001 From: Marco Manfredini Date: Sat, 23 Nov 2024 22:23:41 +0100 Subject: [PATCH 2/4] Remove debugging output --- XmlSchemaClassGenerator/Generator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/XmlSchemaClassGenerator/Generator.cs b/XmlSchemaClassGenerator/Generator.cs index 17819bf..c1783b8 100644 --- a/XmlSchemaClassGenerator/Generator.cs +++ b/XmlSchemaClassGenerator/Generator.cs @@ -24,7 +24,6 @@ public override Uri ResolveUri(Uri baseUri, string relativeUri) { Uri resolvedUri = base.ResolveUri(baseUri, relativeUri); var r=NormalizeUri(baseUri, resolvedUri); - Console.WriteLine($"-- ResolveUri:from {baseUri} to {relativeUri}: {r}"); return r; } private Uri NormalizeUri(Uri baseUri, Uri resolvedUri ) From 456fda836a5c5ab09a049aa74d52428e0b6a22e8 Mon Sep 17 00:00:00 2001 From: phoyd Date: Tue, 26 Nov 2024 12:43:02 +0100 Subject: [PATCH 3/4] Add some unit tests for NormalizingXmlResolverTests --- .../NormalizingXmlResolverTests.cs | 24 +++++++++++++++++++ XmlSchemaClassGenerator.sln.DotSettings | 5 +++- XmlSchemaClassGenerator/Generator.cs | 2 +- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 XmlSchemaClassGenerator.Tests/NormalizingXmlResolverTests.cs diff --git a/XmlSchemaClassGenerator.Tests/NormalizingXmlResolverTests.cs b/XmlSchemaClassGenerator.Tests/NormalizingXmlResolverTests.cs new file mode 100644 index 0000000..2e317fd --- /dev/null +++ b/XmlSchemaClassGenerator.Tests/NormalizingXmlResolverTests.cs @@ -0,0 +1,24 @@ +using System; +using Xunit; + +namespace XmlSchemaClassGenerator.Tests; + +public class NormalizingXmlResolverTests +{ + [Theory] + [InlineData("none", "http://foo.bar.com/baz.xsd", "http://foo.bar.com", "baz.xsd")] + [InlineData("none", "http://x.y.z", "https://foo.bar.com/baz.xsd", "http://x.y.z")] + [InlineData("same", "http://foo.bar.com/baz.xsd", "http://foo.bar.com", "baz.xsd")] + [InlineData("same", "https://x.y.z", "https://foo.bar.com/baz.xsd", "http://x.y.z")] + [InlineData("http", "http://foo.bar.com/baz.xsd", "https://foo.bar.com", "baz.xsd")] + [InlineData("http", "http://x.y.z", "http://foo.bar.com/baz.xsd", "https://x.y.z")] + [InlineData("https", "https://foo.bar.com/baz.xsd", "http://foo.bar.com", "baz.xsd")] + [InlineData("https", "https://x.y.z", "http://foo.bar.com/baz.xsd", "http://x.y.z")] + [InlineData("file", "file://foo.bar.com/baz.xsd", "http://foo.bar.com", "baz.xsd")] + [InlineData("file", "file://x.y.z/a.xsd", "http://foo.bar.com/baz.xsd", "https://x.y.z/a.xsd")] + void TestOverrides(string forceScheme, string expect, string baseUri, string relUri) + { + var res = new XmlSchemaClassGenerator.NormalizingXmlResolver(forceScheme); + Assert.Equal(new Uri(expect),res.ResolveUri(new Uri(baseUri), relUri)); + } +} \ No newline at end of file diff --git a/XmlSchemaClassGenerator.sln.DotSettings b/XmlSchemaClassGenerator.sln.DotSettings index 1160860..4a5d098 100644 --- a/XmlSchemaClassGenerator.sln.DotSettings +++ b/XmlSchemaClassGenerator.sln.DotSettings @@ -2,4 +2,7 @@ DO_NOT_SHOW DO_NOT_SHOW <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> \ No newline at end of file + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy></Policy> + True \ No newline at end of file diff --git a/XmlSchemaClassGenerator/Generator.cs b/XmlSchemaClassGenerator/Generator.cs index c1783b8..aaf940b 100644 --- a/XmlSchemaClassGenerator/Generator.cs +++ b/XmlSchemaClassGenerator/Generator.cs @@ -9,7 +9,7 @@ namespace XmlSchemaClassGenerator { - class NormalizingXmlResolver : XmlUrlResolver + public class NormalizingXmlResolver : XmlUrlResolver { // the Uri scheme to force on the resolved Uris // "none" - do not change Uri scheme From 1afc95e704bbb8cddfc6032335550768b066902e Mon Sep 17 00:00:00 2001 From: phoyd Date: Tue, 26 Nov 2024 12:55:56 +0100 Subject: [PATCH 4/4] Revert changes to DotSettings - changes are not relevant for this pull request. --- XmlSchemaClassGenerator.sln.DotSettings | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/XmlSchemaClassGenerator.sln.DotSettings b/XmlSchemaClassGenerator.sln.DotSettings index 4a5d098..1160860 100644 --- a/XmlSchemaClassGenerator.sln.DotSettings +++ b/XmlSchemaClassGenerator.sln.DotSettings @@ -2,7 +2,4 @@ DO_NOT_SHOW DO_NOT_SHOW <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> - <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"><ExtraRule Prefix="" Suffix="" Style="AaBb" /></Policy></Policy> - True \ No newline at end of file + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> \ No newline at end of file