├── .github ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── pull-request-validator.yml ├── .gitignore ├── .vscode └── settings.json ├── ApiManagementSchemaImport ├── ApiManagementSchemaImport.sln ├── Microsoft.Azure.ApiManagement.Common │ ├── ConsoleLog.cs │ ├── ILog.cs │ └── Microsoft.Azure.ApiManagement.Common.csproj ├── Microsoft.Azure.ApiManagement.WsdlProcessor.App │ ├── Microsoft.Azure.ApiManagement.WsdlProcessor.App.csproj │ ├── Program.cs │ └── appsettings.json ├── Microsoft.Azure.ApiManagement.WsdlProcessor.Common │ ├── CommonResources.Designer.cs │ ├── CommonResources.resx │ ├── DocumentParsingException.cs │ ├── Microsoft.Azure.ApiManagement.WsdlProcessor.Common.csproj │ ├── WsdlDocument.cs │ └── WsdlDocumentException.cs ├── Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App │ ├── Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App.csproj │ └── Program.cs ├── Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common │ ├── Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common.csproj │ └── XmlSchemaDocument.cs ├── Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole │ ├── Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole.csproj │ └── Program.cs ├── TestConsole │ ├── Program.cs │ └── TestConsole.csproj ├── batchWsdlProcessor.ps1 ├── batchXmlSchemaProcessor.ps1 └── uploadschemas.ps1 ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md └── examples ├── WsdlProcessor ├── Include.xsd ├── echoInclude.wsdl └── output.wsdl ├── XmlSchemaProcessor ├── outputFolder │ ├── schema1.xsd │ ├── schema2.xsd │ └── upload-plan.json ├── schema1.xsd └── schema2.xsd ├── batchWsdlProcessor └── configFileWsdl.json ├── batchXmlSchemaProcessor └── configFileXml.json └── uploadSchemas └── upload-plan.json /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /.github/workflows/pull-request-validator.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Build Validator 2 | run-name: Pull Request Build Validator created by ${{ github.actor }} 3 | 4 | on: 5 | pull_request: 6 | types: [opened, synchronize, reopened] 7 | 8 | env: 9 | dotnetVersion: 9.x 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | 19 | - name: Setup .NET 20 | uses: actions/setup-dotnet@v3 21 | with: 22 | dotnet-version: ${{ env.dotnetVersion }} 23 | 24 | - name: Restore dependencies 25 | run: dotnet restore ./ApiManagementSchemaImport/ApiManagementSchemaImport.sln 26 | 27 | - name: Build 28 | run: dotnet build ./ApiManagementSchemaImport/ApiManagementSchemaImport.sln --no-restore 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "markdownlint.config": { 3 | "MD028": false, 4 | "MD025": { 5 | "front_matter_title": "" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /ApiManagementSchemaImport/ApiManagementSchemaImport.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31529.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.ApiManagement.WsdlProcessor.App", "Microsoft.Azure.ApiManagement.WsdlProcessor.App\Microsoft.Azure.ApiManagement.WsdlProcessor.App.csproj", "{4ABFD15B-37F2-4A16-A9A5-A80DC918B0F2}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.ApiManagement.WsdlProcessor.Common", "Microsoft.Azure.ApiManagement.WsdlProcessor.Common\Microsoft.Azure.ApiManagement.WsdlProcessor.Common.csproj", "{FFC31B5C-03C1-4303-96C7-E25052186877}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestConsole", "TestConsole\TestConsole.csproj", "{44D72813-AB99-4230-985C-FFD0E40092A5}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App", "Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App\Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App.csproj", "{5233A8EC-5B87-43AD-B993-655CCC6EB455}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common", "Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common\Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common.csproj", "{8FC578CA-8FD6-412A-9B46-48152458D816}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole", "Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole\Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole.csproj", "{15848C1D-60C0-456B-8A2A-7ACFA83AFC31}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Azure.ApiManagement.Common", "Microsoft.Azure.ApiManagement.Common\Microsoft.Azure.ApiManagement.Common.csproj", "{375671A0-1996-4D1B-813F-6F7BBBE5F16B}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {4ABFD15B-37F2-4A16-A9A5-A80DC918B0F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {4ABFD15B-37F2-4A16-A9A5-A80DC918B0F2}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {4ABFD15B-37F2-4A16-A9A5-A80DC918B0F2}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {4ABFD15B-37F2-4A16-A9A5-A80DC918B0F2}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {FFC31B5C-03C1-4303-96C7-E25052186877}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {FFC31B5C-03C1-4303-96C7-E25052186877}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {FFC31B5C-03C1-4303-96C7-E25052186877}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {FFC31B5C-03C1-4303-96C7-E25052186877}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {44D72813-AB99-4230-985C-FFD0E40092A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {44D72813-AB99-4230-985C-FFD0E40092A5}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {44D72813-AB99-4230-985C-FFD0E40092A5}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {44D72813-AB99-4230-985C-FFD0E40092A5}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {5233A8EC-5B87-43AD-B993-655CCC6EB455}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {5233A8EC-5B87-43AD-B993-655CCC6EB455}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {5233A8EC-5B87-43AD-B993-655CCC6EB455}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {5233A8EC-5B87-43AD-B993-655CCC6EB455}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {8FC578CA-8FD6-412A-9B46-48152458D816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {8FC578CA-8FD6-412A-9B46-48152458D816}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {8FC578CA-8FD6-412A-9B46-48152458D816}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {8FC578CA-8FD6-412A-9B46-48152458D816}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {15848C1D-60C0-456B-8A2A-7ACFA83AFC31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {15848C1D-60C0-456B-8A2A-7ACFA83AFC31}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {15848C1D-60C0-456B-8A2A-7ACFA83AFC31}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {15848C1D-60C0-456B-8A2A-7ACFA83AFC31}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {375671A0-1996-4D1B-813F-6F7BBBE5F16B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {375671A0-1996-4D1B-813F-6F7BBBE5F16B}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {375671A0-1996-4D1B-813F-6F7BBBE5F16B}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {375671A0-1996-4D1B-813F-6F7BBBE5F16B}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(ExtensibilityGlobals) = postSolution 59 | SolutionGuid = {605FBF9A-0F9D-4586-AE7E-749C92A40148} 60 | EndGlobalSection 61 | EndGlobal 62 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.Common/ConsoleLog.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.ApiManagement.Common; 2 | 3 | public class ConsoleLog : ILog 4 | { 5 | public void Critical(string eventName) 6 | { 7 | Console.WriteLine("Critical : " + eventName); 8 | } 9 | 10 | public void Critical(string eventName, string message) 11 | { 12 | Console.WriteLine("Critical : " + eventName + " : " + message); 13 | } 14 | 15 | public void Critical(string eventName, Exception ex) 16 | { 17 | Console.WriteLine("Critical : " + eventName + " : Exception : " + ex.Message); 18 | } 19 | 20 | public void Critical(string eventName, string message, Exception ex) 21 | { 22 | Console.WriteLine("Critical : " + eventName + " : " + message + " : Exception : " + ex.Message); 23 | } 24 | 25 | public void Critical(string eventName, string message, Exception ex, params object[] args) 26 | { 27 | Console.WriteLine("Critical : " + eventName + " : " + message + " : Exception : " + ex.Message); 28 | } 29 | 30 | public void Error(string eventName) 31 | { 32 | Console.WriteLine("Error : " + eventName); 33 | } 34 | 35 | public void Error(string eventName, string message) 36 | { 37 | Console.WriteLine("Error : " + eventName + " : " + message); 38 | } 39 | 40 | public void Error(string eventName, Exception ex) 41 | { 42 | Console.WriteLine("Error : " + eventName + " : Exception : " + ex.Message); 43 | } 44 | 45 | public void Error(string eventName, string message, Exception ex) 46 | { 47 | Console.WriteLine("Error : " + eventName + " : " + message + " : Exception : " + ex.Message); 48 | } 49 | 50 | public void Error(string eventName, string message, Exception ex, params object[] args) 51 | { 52 | Console.WriteLine("Error : " + eventName + " : " + message + " : Exception : " + ex.Message); 53 | } 54 | 55 | public void Informational(string eventName) 56 | { 57 | Console.WriteLine("Info : " + eventName); 58 | } 59 | 60 | public void Informational(string eventName, string message) 61 | { 62 | Console.WriteLine("Info : " + eventName + " : " + message); 63 | } 64 | 65 | public void Informational(string eventName, Exception ex) 66 | { 67 | Console.WriteLine("Info : " + eventName + " : Exception : " + ex.Message); 68 | } 69 | 70 | public void Informational(string eventName, string message, Exception ex) 71 | { 72 | Console.WriteLine("Info : " + eventName + " : " + message + " : Exception : " + ex.Message); 73 | } 74 | 75 | public void Informational(string eventName, string message, Exception ex, params object[] args) 76 | { 77 | Console.WriteLine("Info : " + eventName + " : " + message + " : Exception : " + ex.Message); 78 | } 79 | 80 | public void Verbose(string eventName) 81 | { 82 | Console.WriteLine("Verbose : " + eventName); 83 | } 84 | 85 | public void Verbose(string eventName, string message) 86 | { 87 | Console.WriteLine("Verbose : " + eventName + " : " + message); 88 | } 89 | 90 | public void Verbose(string eventName, Exception ex) 91 | { 92 | Console.WriteLine("Verbose : " + eventName + " : Exception : " + ex.Message); 93 | } 94 | 95 | public void Verbose(string eventName, string message, Exception ex) 96 | { 97 | Console.WriteLine("Verbose : " + eventName + " : " + message + " : Exception : " + ex.Message); 98 | } 99 | 100 | public void Verbose(string eventName, string message, Exception ex, params object[] args) 101 | { 102 | Console.WriteLine("Verbose : " + eventName + " : " + message + " : Exception : " + ex.Message); 103 | } 104 | 105 | public void Warning(string eventName) 106 | { 107 | Console.WriteLine("Warning : " + eventName); 108 | } 109 | 110 | public void Warning(string eventName, string message) 111 | { 112 | Console.WriteLine("Warning : " + eventName + " : " + message); 113 | } 114 | 115 | public void Warning(string eventName, Exception ex) 116 | { 117 | Console.WriteLine("Warning : " + eventName + " : Exception : " + ex.Message); 118 | } 119 | 120 | public void Warning(string eventName, string message, Exception ex) 121 | { 122 | Console.WriteLine("Warning : " + eventName + " : " + message + " : Exception : " + ex.Message); 123 | } 124 | 125 | public void Warning(string eventName, string message, Exception ex, params object[] args) 126 | { 127 | Console.WriteLine("Warning : " + eventName + " : " + message + " : Exception : " + ex.Message); 128 | } 129 | 130 | public void Success(string msg) 131 | { 132 | Console.WriteLine("Success : " + msg); 133 | } 134 | } -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.Common/ILog.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Azure.ApiManagement.Common 2 | { 3 | public interface ILog 4 | { 5 | void Verbose(string eventName); 6 | 7 | void Verbose(string eventName, string message); 8 | 9 | void Verbose(string eventName, Exception ex); 10 | 11 | void Verbose(string eventName, string message, Exception ex); 12 | 13 | void Verbose(string eventName, string message, Exception ex, params object[] args); 14 | 15 | void Informational(string eventName); 16 | 17 | void Informational(string eventName, string message); 18 | 19 | void Informational(string eventName, Exception ex); 20 | 21 | void Informational(string eventName, string message, Exception ex); 22 | 23 | void Informational(string eventName, string message, Exception ex, params object[] args); 24 | 25 | void Warning(string eventName); 26 | 27 | void Warning(string eventName, string message); 28 | 29 | void Warning(string eventName, Exception ex); 30 | 31 | void Warning(string eventName, string message, Exception ex); 32 | 33 | void Warning(string eventName, string message, Exception ex, params object[] args); 34 | 35 | void Error(string eventName); 36 | 37 | void Error(string eventName, string message); 38 | 39 | void Error(string eventName, Exception ex); 40 | 41 | void Error(string eventName, string message, Exception ex); 42 | 43 | void Error(string eventName, string message, Exception ex, params object[] args); 44 | 45 | void Critical(string eventName); 46 | 47 | void Critical(string eventName, string message); 48 | 49 | void Critical(string eventName, Exception ex); 50 | 51 | void Critical(string eventName, string message, Exception ex); 52 | 53 | void Critical(string eventName, string message, Exception ex, params object[] args); 54 | 55 | void Success(string msg); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.Common/Microsoft.Azure.ApiManagement.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.App/Microsoft.Azure.ApiManagement.WsdlProcessor.App.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.App/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.ApiManagement.WsdlProcessor.Common; 2 | using System; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | using System.Xml; 6 | using System.Xml.Linq; 7 | 8 | namespace Microsoft.Azure.ApiManagement.WsdlProcessor.App 9 | { 10 | class Program 11 | { 12 | static async Task Main(string[] args) 13 | { 14 | string wsdlFile, outputFile = string.Empty; 15 | 16 | var log = new ConsoleLog(); 17 | int exitCode = 0; 18 | 19 | if (args.Length == 2) 20 | { 21 | wsdlFile = args[0]; 22 | if (!File.Exists(wsdlFile)) 23 | { 24 | var msg = $"The input file {wsdlFile} does not exists or we cannot access."; 25 | log.Error(msg); 26 | throw new Exception(msg); 27 | } 28 | 29 | wsdlFile = wsdlFile.Contains(".wsdl") ? wsdlFile : wsdlFile + ".wsdl"; 30 | 31 | outputFile = args[1]; 32 | outputFile = Path.IsPathRooted(outputFile) ? outputFile : Path.Join(Directory.GetCurrentDirectory(), outputFile); 33 | } 34 | else 35 | { 36 | Console.WriteLine("Please fill the corrects parameters."); 37 | Console.WriteLine("Parameters 1 = WSDL file path."); 38 | Console.WriteLine("Parameters 2 = Output file path."); 39 | Environment.Exit(1); 40 | 41 | return; 42 | } 43 | 44 | try 45 | { 46 | var wsdlString = File.ReadAllText(wsdlFile); 47 | var xDocument = XDocument.Parse(wsdlString); 48 | await WsdlDocument.LoadAsync(xDocument.Root, log); 49 | 50 | xDocument.Root.Save(outputFile); 51 | 52 | Console.WriteLine(); 53 | Console.WriteLine(); 54 | 55 | log.Success($"*** WSDL file {wsdlFile} processed successfully and generate file {outputFile}."); 56 | } 57 | catch (XmlException e) 58 | { 59 | exitCode = 1; 60 | log.Error($"{e.Message}"); 61 | log.Error($"Location {wsdlFile} contains invalid xml: {e.StackTrace}"); 62 | } 63 | catch (Exception e) 64 | { 65 | exitCode = 1; 66 | log.Error($"{e.Message}"); 67 | log.Error($"Stacktrace: {e.StackTrace}"); 68 | } 69 | 70 | Environment.Exit(exitCode); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.App/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "HttpTimeoutMilliseconds": 10000 3 | } -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.Common/CommonResources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Microsoft.Azure.ApiManagement.WsdlProcessor.Common { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class CommonResources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal CommonResources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.ApiManagement.WsdlProcessor.Common.CommonResources", typeof(CommonResources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Binding '{0}' not found.. 65 | /// 66 | internal static string BindingNotFound { 67 | get { 68 | return ResourceManager.GetString("BindingNotFound", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Could not resolve type '{0}'.. 74 | /// 75 | internal static string CannotResolveType { 76 | get { 77 | return ResourceManager.GetString("CannotResolveType", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Could not retrieve import from '{0}'. The request failed with error '{1}' and message '{2}'.. 83 | /// 84 | internal static string FailedToImport { 85 | get { 86 | return ResourceManager.GetString("FailedToImport", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to Could not retrieve import from '{0}'. The request response code was '{1}' and parsing the response content failed with '{2}' and message '{3}'.. 92 | /// 93 | internal static string FailedToParseImportedSchemaResponse { 94 | get { 95 | return ResourceManager.GetString("FailedToParseImportedSchemaResponse", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to Cannot resolve referenced input message '{0}'.. 101 | /// 102 | internal static string InputMessageNotFound { 103 | get { 104 | return ResourceManager.GetString("InputMessageNotFound", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Looks up a localized string similar to Interface '{0}' not found.. 110 | /// 111 | internal static string InterfaceNotFound { 112 | get { 113 | return ResourceManager.GetString("InterfaceNotFound", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized string similar to The provided schema '{0}' is invalid and cannot be parsed.. 119 | /// 120 | internal static string InvalidXmlSchema { 121 | get { 122 | return ResourceManager.GetString("InvalidXmlSchema", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Looks up a localized string similar to Loaded '{0}' bindings.. 128 | /// 129 | internal static string LoadedBindings { 130 | get { 131 | return ResourceManager.GetString("LoadedBindings", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// Looks up a localized string similar to Loaded '{0}' interfaces.. 137 | /// 138 | internal static string LoadedInterfaces { 139 | get { 140 | return ResourceManager.GetString("LoadedInterfaces", resourceCulture); 141 | } 142 | } 143 | 144 | /// 145 | /// Looks up a localized string similar to Loaded '{0}' messages.. 146 | /// 147 | internal static string LoadedMessages { 148 | get { 149 | return ResourceManager.GetString("LoadedMessages", resourceCulture); 150 | } 151 | } 152 | 153 | /// 154 | /// Looks up a localized string similar to No schemas found.. 155 | /// 156 | internal static string LoadedNoSchemas { 157 | get { 158 | return ResourceManager.GetString("LoadedNoSchemas", resourceCulture); 159 | } 160 | } 161 | 162 | /// 163 | /// Looks up a localized string similar to Target Namespace: '{0}'.. 164 | /// 165 | internal static string LoadedSchema { 166 | get { 167 | return ResourceManager.GetString("LoadedSchema", resourceCulture); 168 | } 169 | } 170 | 171 | /// 172 | /// Looks up a localized string similar to Loaded '{0}' schemas.. 173 | /// 174 | internal static string LoadedSchemas { 175 | get { 176 | return ResourceManager.GetString("LoadedSchemas", resourceCulture); 177 | } 178 | } 179 | 180 | /// 181 | /// Looks up a localized string similar to Loaded '{0}' services.. 182 | /// 183 | internal static string LoadedServices { 184 | get { 185 | return ResourceManager.GetString("LoadedServices", resourceCulture); 186 | } 187 | } 188 | 189 | /// 190 | /// Looks up a localized string similar to Loaded '{0}' types.. 191 | /// 192 | internal static string LoadedTypes { 193 | get { 194 | return ResourceManager.GetString("LoadedTypes", resourceCulture); 195 | } 196 | } 197 | 198 | /// 199 | /// Looks up a localized string similar to No interfaces found.. 200 | /// 201 | internal static string NoInterfacesFound { 202 | get { 203 | return ResourceManager.GetString("NoInterfacesFound", resourceCulture); 204 | } 205 | } 206 | 207 | /// 208 | /// Looks up a localized string similar to Notification Operation '{0}' is not supported. Only Request-response and Solicit-response Operations are supported.. 209 | /// 210 | internal static string NotificationOperationNotSupported { 211 | get { 212 | return ResourceManager.GetString("NotificationOperationNotSupported", resourceCulture); 213 | } 214 | } 215 | 216 | /// 217 | /// Looks up a localized string similar to One-way Operation '{0}' is not supported. Only Request-response and Solicit-response Operations are supported.. 218 | /// 219 | internal static string OneWayOperationNotSupported { 220 | get { 221 | return ResourceManager.GetString("OneWayOperationNotSupported", resourceCulture); 222 | } 223 | } 224 | 225 | /// 226 | /// Looks up a localized string similar to Unable to generate unique resource identifiers for operations, both operation names and SOAP actions conflict. Please modify the WSDL document to avoid redundant operation names, including redundant use of empty string.. 227 | /// 228 | internal static string OperationsActionsBothDoConflict { 229 | get { 230 | return ResourceManager.GetString("OperationsActionsBothDoConflict", resourceCulture); 231 | } 232 | } 233 | 234 | /// 235 | /// Looks up a localized string similar to Cannot resolve referenced output message '{0}'.. 236 | /// 237 | internal static string OutputMessageNotFound { 238 | get { 239 | return ResourceManager.GetString("OutputMessageNotFound", resourceCulture); 240 | } 241 | } 242 | 243 | /// 244 | /// Looks up a localized string similar to Completed parsing XML.. 245 | /// 246 | internal static string ParsingXmlComplete { 247 | get { 248 | return ResourceManager.GetString("ParsingXmlComplete", resourceCulture); 249 | } 250 | } 251 | 252 | /// 253 | /// Looks up a localized string similar to Started parsing XML.. 254 | /// 255 | internal static string ParsingXmlStarted { 256 | get { 257 | return ResourceManager.GetString("ParsingXmlStarted", resourceCulture); 258 | } 259 | } 260 | 261 | /// 262 | /// Looks up a localized string similar to Element named '{0}' has a recursive definition. Recursive types are not supported.. 263 | /// 264 | internal static string RecursiveTypesNotSupported { 265 | get { 266 | return ResourceManager.GetString("RecursiveTypesNotSupported", resourceCulture); 267 | } 268 | } 269 | 270 | /// 271 | /// Looks up a localized string similar to Schemas only allow Imports or Includes.. 272 | /// 273 | internal static string SchemaOnlyAllowsIncludeOrImport { 274 | get { 275 | return ResourceManager.GetString("SchemaOnlyAllowsIncludeOrImport", resourceCulture); 276 | } 277 | } 278 | 279 | /// 280 | /// Looks up a localized string similar to A soap:address element with location attribute is required in the wsdl:port element named '{0}' of the WSDL document.. 281 | /// 282 | internal static string SoapAddressLocationRequired { 283 | get { 284 | return ResourceManager.GetString("SoapAddressLocationRequired", resourceCulture); 285 | } 286 | } 287 | 288 | /// 289 | /// Looks up a localized string similar to Unable to import API from WSDL.. 290 | /// 291 | internal static string UnableToImportApiFromWsdl { 292 | get { 293 | return ResourceManager.GetString("UnableToImportApiFromWsdl", resourceCulture); 294 | } 295 | } 296 | 297 | /// 298 | /// Looks up a localized string similar to Unable to parse WSDL.. 299 | /// 300 | internal static string UnableToParseWsdl { 301 | get { 302 | return ResourceManager.GetString("UnableToParseWsdl", resourceCulture); 303 | } 304 | } 305 | 306 | /// 307 | /// Looks up a localized string similar to Unexpected null binding operation or null operation. Please check the WSDL document operations and bindings.. 308 | /// 309 | internal static string UnexpectedNullOperationOrBinding { 310 | get { 311 | return ResourceManager.GetString("UnexpectedNullOperationOrBinding", resourceCulture); 312 | } 313 | } 314 | 315 | /// 316 | /// Looks up a localized string similar to Unknown WSDL Version: '{0}'.. 317 | /// 318 | internal static string UnknownWsdlVersion { 319 | get { 320 | return ResourceManager.GetString("UnknownWsdlVersion", resourceCulture); 321 | } 322 | } 323 | 324 | /// 325 | /// Looks up a localized string similar to WSDL 2.0 currently not supported for import.. 326 | /// 327 | internal static string Wsdl20CurrentlyNotSupported { 328 | get { 329 | return ResourceManager.GetString("Wsdl20CurrentlyNotSupported", resourceCulture); 330 | } 331 | } 332 | 333 | /// 334 | /// Looks up a localized string similar to WsdlVersion: '{0}' TargetNamespace: '{1}'.. 335 | /// 336 | internal static string WsdlIdentification { 337 | get { 338 | return ResourceManager.GetString("WsdlIdentification", resourceCulture); 339 | } 340 | } 341 | 342 | /// 343 | /// Looks up a localized string similar to XSD Schema http://www.w3.org/2000/10/XMLSchema is not supported. Use http://www.w3.org/2001/XMLSchema instead.. 344 | /// 345 | internal static string WsdlImportRuleCheckXmlSchemaNamespace { 346 | get { 347 | return ResourceManager.GetString("WsdlImportRuleCheckXmlSchemaNamespace", resourceCulture); 348 | } 349 | } 350 | 351 | /// 352 | /// Looks up a localized string similar to WSDL Import is currently not supported.. 353 | /// 354 | internal static string WsdlImportRuleImportNotSupported { 355 | get { 356 | return ResourceManager.GetString("WsdlImportRuleImportNotSupported", resourceCulture); 357 | } 358 | } 359 | 360 | /// 361 | /// Looks up a localized string similar to Message '{0}' contains multiple parts.. 362 | /// 363 | internal static string WsdlImportRuleSingleParts { 364 | get { 365 | return ResourceManager.GetString("WsdlImportRuleSingleParts", resourceCulture); 366 | } 367 | } 368 | 369 | /// 370 | /// Looks up a localized string similar to WSDL message '{0}' has no name attribute. The name attribute is required per WSDL 1.1 specification.. 371 | /// 372 | internal static string WsdlMessageNameAttributeNotFound { 373 | get { 374 | return ResourceManager.GetString("WsdlMessageNameAttributeNotFound", resourceCulture); 375 | } 376 | } 377 | 378 | /// 379 | /// Looks up a localized string similar to Completed WSDL verification. WSDL is considered valid.. 380 | /// 381 | internal static string WsdlPrecheckComplete { 382 | get { 383 | return ResourceManager.GetString("WsdlPrecheckComplete", resourceCulture); 384 | } 385 | } 386 | 387 | /// 388 | /// Looks up a localized string similar to Failed WSDL verification.. 389 | /// 390 | internal static string WsdlPrecheckFailed { 391 | get { 392 | return ResourceManager.GetString("WsdlPrecheckFailed", resourceCulture); 393 | } 394 | } 395 | 396 | /// 397 | /// Looks up a localized string similar to Location: '{0}' TargetNamespace: '{1}'.. 398 | /// 399 | internal static string XsdImport { 400 | get { 401 | return ResourceManager.GetString("XsdImport", resourceCulture); 402 | } 403 | } 404 | 405 | /// 406 | /// Looks up a localized string similar to FROM: '{0}' BEGIN. 407 | /// 408 | internal static string XsdImportBegin { 409 | get { 410 | return ResourceManager.GetString("XsdImportBegin", resourceCulture); 411 | } 412 | } 413 | 414 | /// 415 | /// Looks up a localized string similar to FROM: '{0}' END. 416 | /// 417 | internal static string XsdImportEnd { 418 | get { 419 | return ResourceManager.GetString("XsdImportEnd", resourceCulture); 420 | } 421 | } 422 | 423 | /// 424 | /// Looks up a localized string similar to Location '{0}' cannot be resolved. Cannot resolve WSDL Imports that use relative URLs.. 425 | /// 426 | internal static string XsdImportFailure { 427 | get { 428 | return ResourceManager.GetString("XsdImportFailure", resourceCulture); 429 | } 430 | } 431 | 432 | /// 433 | /// Looks up a localized string similar to Found '{0}' imports.. 434 | /// 435 | internal static string XsdImportsFound { 436 | get { 437 | return ResourceManager.GetString("XsdImportsFound", resourceCulture); 438 | } 439 | } 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.Common/CommonResources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Binding '{0}' not found. 122 | 123 | 124 | Could not resolve type '{0}'. 125 | 126 | 127 | Could not retrieve import from '{0}'. The request failed with error '{1}' and message '{2}'. 128 | 129 | 130 | Could not retrieve import from '{0}'. The request response code was '{1}' and parsing the response content failed with '{2}' and message '{3}'. 131 | 132 | 133 | Cannot resolve referenced input message '{0}'. 134 | 135 | 136 | Interface '{0}' not found. 137 | 138 | 139 | The provided schema '{0}' is invalid and cannot be parsed. 140 | 141 | 142 | Loaded '{0}' bindings. 143 | 144 | 145 | Loaded '{0}' interfaces. 146 | 147 | 148 | Loaded '{0}' messages. 149 | 150 | 151 | No schemas found. 152 | 153 | 154 | Target Namespace: '{0}'. 155 | 156 | 157 | Loaded '{0}' schemas. 158 | 159 | 160 | Loaded '{0}' services. 161 | 162 | 163 | Loaded '{0}' types. 164 | 165 | 166 | No interfaces found. 167 | 168 | 169 | Notification Operation '{0}' is not supported. Only Request-response and Solicit-response Operations are supported. 170 | 171 | 172 | One-way Operation '{0}' is not supported. Only Request-response and Solicit-response Operations are supported. 173 | 174 | 175 | Unable to generate unique resource identifiers for operations, both operation names and SOAP actions conflict. Please modify the WSDL document to avoid redundant operation names, including redundant use of empty string. 176 | 177 | 178 | Cannot resolve referenced output message '{0}'. 179 | 180 | 181 | Completed parsing XML. 182 | 183 | 184 | Started parsing XML. 185 | 186 | 187 | Element named '{0}' has a recursive definition. Recursive types are not supported. 188 | 189 | 190 | Schemas only allow Imports or Includes. 191 | 192 | 193 | A soap:address element with location attribute is required in the wsdl:port element named '{0}' of the WSDL document. 194 | 195 | 196 | Unable to import API from WSDL. 197 | 198 | 199 | Unable to parse WSDL. 200 | 201 | 202 | Unexpected null binding operation or null operation. Please check the WSDL document operations and bindings. 203 | 204 | 205 | Unknown WSDL Version: '{0}'. 206 | 207 | 208 | WSDL 2.0 currently not supported for import. 209 | 210 | 211 | WsdlVersion: '{0}' TargetNamespace: '{1}'. 212 | 213 | 214 | XSD Schema http://www.w3.org/2000/10/XMLSchema is not supported. Use http://www.w3.org/2001/XMLSchema instead. 215 | 216 | 217 | WSDL Import is currently not supported. 218 | 219 | 220 | Message '{0}' contains multiple parts. 221 | 222 | 223 | WSDL message '{0}' has no name attribute. The name attribute is required per WSDL 1.1 specification. 224 | 225 | 226 | Completed WSDL verification. WSDL is considered valid. 227 | 228 | 229 | Failed WSDL verification. 230 | 231 | 232 | Location: '{0}' TargetNamespace: '{1}'. 233 | 234 | 235 | FROM: '{0}' BEGIN 236 | 237 | 238 | FROM: '{0}' END 239 | 240 | 241 | Location '{0}' cannot be resolved. Cannot resolve WSDL Imports that use relative URLs. 242 | 243 | 244 | Found '{0}' imports. 245 | 246 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.Common/DocumentParsingException.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // -------------------------------------------------------------------------- 6 | 7 | namespace Microsoft.Azure.ApiManagement.WsdlProcessor.Common 8 | { 9 | using System; 10 | 11 | [Serializable] 12 | public class DocumentParsingException : Exception 13 | { 14 | public DocumentParsingException(string message) : base(message) 15 | { 16 | } 17 | 18 | public DocumentParsingException(string message, string report) : base(message) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.Common/Microsoft.Azure.ApiManagement.WsdlProcessor.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | 6 | 7 | 8 | 9 | True 10 | True 11 | CommonResources.resx 12 | 13 | 14 | 15 | 16 | 17 | ResXFileCodeGenerator 18 | CommonResources.Designer.cs 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.Common/WsdlDocument.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // -------------------------------------------------------------------------- 6 | using Microsoft.Azure.ApiManagement.Common; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Net.Http; 12 | using System.Threading.Tasks; 13 | using System.Xml; 14 | using System.Xml.Linq; 15 | using System.Xml.Schema; 16 | 17 | namespace Microsoft.Azure.ApiManagement.WsdlProcessor.Common 18 | { 19 | // WS-I Basic Profile 1.1 : use SOAP 1.1, WSDL 1.1 and UDDI 2.0 20 | // WS-I Basic Profile 1.2 (9th Nov, 2010) specifies the usage of SOAP 1.1, WSDL 1.1, UDDI 2.0, WS-Addressing 1.0 and MTOM 21 | // WS-I Basic Profile 2.0 (9th Nov, 2010) specifies the usage of SOAP 1.2, WSDL 1.1, UDDI 2.0, WS-Addressing and MTOM. 22 | // http://www.w3.org/2003/06/soap11-soap12.html 23 | 24 | public enum WsdlVersionLiteral 25 | { 26 | Wsdl11, 27 | Wsdl20 // Almost never used and currently not supported 28 | } 29 | 30 | public class WsdlDocument 31 | { 32 | public const string Wsdl11Namespace = "http://schemas.xmlsoap.org/wsdl/"; 33 | 34 | public const string Wsdl20Namespace = "http://www.w3.org/ns/wsdl"; 35 | 36 | public const string DefaultPrefix = "MS"; 37 | 38 | //public IList RootAttributes { get; set; } 39 | 40 | public static XNamespace WsdlSoap12Namespace = XNamespace.Get("http://schemas.xmlsoap.org/wsdl/soap12/"); 41 | 42 | public static XNamespace WsdlSoap11Namespace = XNamespace.Get("http://schemas.xmlsoap.org/wsdl/soap/"); 43 | 44 | public static XNamespace WsAddressingWsdlNamespace = XNamespace.Get("http://www.w3.org/2006/05/addressing/wsdl"); 45 | 46 | public static XNamespace WsAddressingNamespace = XNamespace.Get("http://www.w3.org/2006/05/addressing"); 47 | 48 | public static XNamespace XsdSchemaNamespace = XNamespace.Get("http://www.w3.org/2001/XMLSchema"); 49 | 50 | public static XNamespace XsdSchemaInstanceNamespace = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance"); 51 | 52 | public static string[] XsdTypes = new string[] { "anyURI", "base64Binary", "boolean", "date", "dateTime", "decimal", "double", "duration", "float", "hexBinary", "gDay", "gMonth", "gMonthDay", "gYear", "gYearMonth", "NOTATION", "QName", "string", "time", "integer" }; 53 | 54 | public XNamespace TargetNamespace { get; set; } 55 | 56 | public WsdlVersionLiteral WsdlVersion { get; set; } 57 | 58 | public XNamespace WsdlNamespace 59 | { 60 | get 61 | { 62 | return this.WsdlVersion == WsdlVersionLiteral.Wsdl11 ? Wsdl11Namespace : Wsdl20Namespace; 63 | } 64 | } 65 | 66 | public Dictionary Schemas { get; set; } 67 | 68 | public Dictionary> Imports { get; set; } 69 | 70 | readonly ILog logger; 71 | 72 | public WsdlDocument(ILog logger) 73 | { 74 | this.WsdlVersion = WsdlVersionLiteral.Wsdl11; 75 | this.logger = logger; 76 | } 77 | 78 | private static XNamespace GetTargetNamespace(XElement element) 79 | { 80 | XNamespace targetNamespace = XNamespace.None; 81 | XAttribute attr = element.Attribute("targetNamespace"); 82 | 83 | if (attr != null) 84 | { 85 | targetNamespace = XNamespace.Get(attr.Value); 86 | } 87 | 88 | return targetNamespace; 89 | } 90 | 91 | /// 92 | /// Loads a WSDL Document from an . 93 | /// 94 | /// 95 | /// The document is not verified for support and may result in unhandled exceptions. 96 | /// Use of this method is preferred for trusted documents that have already been verified 97 | /// and do not require further verification such as documents already saved. 98 | /// 99 | /// The containing the WSDL. 100 | /// A logger for parsing events. 101 | /// A UNC Path about schemaLocations. 102 | public static async Task LoadAsync(XElement documentElement, ILog logger) 103 | { 104 | var doc = new WsdlDocument(logger) 105 | { 106 | WsdlVersion = DetermineVersion(documentElement.Name.Namespace), 107 | 108 | TargetNamespace = GetTargetNamespace(documentElement), 109 | 110 | Imports = new Dictionary>() 111 | }; 112 | 113 | logger.Informational("WsdlIdentification", string.Format( 114 | CommonResources.WsdlIdentification, 115 | doc.WsdlVersion, 116 | doc.TargetNamespace.NamespaceName)); 117 | 118 | await ProcessWsdlImports(doc, documentElement, logger); 119 | 120 | //doc.RootAttributes = documentElement.Attributes().Where(a => a.ToString().Contains("xmlns:")).ToList(); 121 | 122 | XElement types = documentElement.Element(doc.WsdlNamespace + "types"); 123 | 124 | if (types != null) 125 | { 126 | ILookup targetNamespaces = types.Elements(XsdSchemaNamespace + "schema") 127 | .ToLookup( 128 | k => 129 | { 130 | XNamespace key = GetTargetNamespace(k); 131 | logger.Informational("LoadedSchema", string.Format( 132 | CommonResources.LoadedSchema, 133 | key.NamespaceName)); 134 | return key; 135 | }, 136 | v => v); 137 | 138 | // Merge duplicate schemas 139 | doc.Schemas = targetNamespaces.Select(s => 140 | { 141 | XElement schema = s.First(); 142 | MergeSchemas(schema, s.Skip(1).ToList()); 143 | return new { key = s.Key, value = schema }; 144 | }).ToDictionary(k => k.key, v => v.value); 145 | 146 | await ProcessXsdImportsIncludes(doc, logger); 147 | 148 | logger.Informational("LoadedSchemas", string.Format(CommonResources.LoadedSchemas, doc.Schemas.Count)); 149 | } 150 | else 151 | { 152 | doc.Schemas = new Dictionary(); 153 | logger.Warning("LoadedSchemas", CommonResources.LoadedNoSchemas); 154 | } 155 | 156 | types.Elements().Remove(); 157 | 158 | foreach (var schema in doc.Schemas) 159 | { 160 | //if (!types.Elements(XsdSchemaNamespace + "schema").Any(i => i.ToString().Equals(schema.Value.ToString(), StringComparison.InvariantCultureIgnoreCase) || schema.Key.NamespaceName.Equals(i.Attribute("targetNamespace")?.Value))) 161 | //{ 162 | types.Add(schema.Value); 163 | //} 164 | } 165 | 166 | //Adding imports to each schema 167 | foreach (var schema in types.Elements(XsdSchemaNamespace + "schema").Where(e => e.Attribute("targetNamespace") != null)) 168 | { 169 | if (doc.Imports.TryGetValue(schema.Attribute("targetNamespace")?.Value, out var imports)) 170 | { 171 | foreach (var item in imports) 172 | { 173 | schema.AddFirst(new XElement(XsdSchemaNamespace + "import", new XAttribute("namespace", item))); 174 | } 175 | } 176 | } 177 | 178 | //Removing third party elements from documentElement 179 | var listToRemove = new List(); 180 | 181 | var allowedPrefixes = documentElement 182 | .Attributes() 183 | .Where(a => a.ToString().Contains("xmlns:")) 184 | .Select(a => a.Name.LocalName) 185 | .ToHashSet(); 186 | 187 | documentElement.Elements().Where(e => !e.Name.LocalName.Equals("types")).DescendantsAndSelf(). 188 | Where(x => !x.Name.NamespaceName.Equals(Wsdl11Namespace) 189 | && !x.Name.NamespaceName.Equals(XsdSchemaNamespace.NamespaceName) 190 | && !allowedPrefixes.Contains(x.GetPrefixOfNamespace(x.Name.Namespace))) 191 | .ToList() 192 | .ForEach(i => listToRemove.Add(i)); 193 | 194 | //Another approach to remove third party elements is with Schema Validation. 195 | listToRemove.ForEach(i => i.Remove()); 196 | } 197 | 198 | /// 199 | /// Merges all wsdl:imports in parent WSDL. 200 | /// 201 | /// 202 | /// 203 | /// 204 | /// 205 | private static async Task ProcessWsdlImports(WsdlDocument doc, XElement documentElement, ILog logger) 206 | { 207 | var wsdlImports = documentElement.Elements(doc.WsdlNamespace + "import") 208 | .Select(e => new 209 | { 210 | Location = e.Attribute("location").Value, 211 | Namespace = e.Attribute("namespace")?.Value 212 | }) 213 | .ToHashSet(); 214 | documentElement.Elements(doc.WsdlNamespace + "import").Remove(); 215 | //var rootAttributes = documentElement.Attributes().Where(a => a.ToString().Contains("xmlns:")).Select(a => a.ToString().Split('=')[0]).ToHashSet(); 216 | var attributesToAdd = new List(); 217 | var elementsToAdd = new List(); 218 | 219 | while (wsdlImports.Count > 0) 220 | { 221 | var import = wsdlImports.First(); 222 | wsdlImports.Remove(import); 223 | //TODO: Add log messages 224 | var wsdlText = await GetStringDocumentFromUri(logger, import.Location); 225 | 226 | var importXDocument = XDocument.Parse(wsdlText); 227 | var xDocument = importXDocument.Root; 228 | var elements = xDocument.Elements().Reverse(); 229 | 230 | //Modify the elements before adding them to WSDL parent 231 | AddXmlnsAndChangePrefixReferenced(documentElement, elements, xDocument.Attributes(). 232 | Where(a => a.ToString().Contains("xmlns:")).ToDictionary(a => a.Value, a => a.Name.LocalName)); 233 | 234 | elementsToAdd.AddRange(elements); 235 | //We need to check for new wsdl:imports 236 | var newImports = xDocument.Elements(doc.WsdlNamespace + "import") 237 | .Select(e => new 238 | { 239 | Location = e.Attribute("location").Value, 240 | Namespace = e.Attribute("namespace")?.Value 241 | }) 242 | .ToHashSet(); 243 | wsdlImports.Union(newImports); 244 | } 245 | 246 | elementsToAdd.ForEach(i => documentElement.AddFirst(i)); 247 | ChangeElementsToParentTargetNamespace(doc, documentElement); 248 | } 249 | 250 | /// 251 | /// Process all XSD Imports and Includes 252 | /// 253 | /// doc.Schemas where all the imports are added 254 | /// 255 | /// 256 | /// 257 | private static async Task ProcessXsdImportsIncludes(WsdlDocument doc, ILog logger) 258 | { 259 | if (doc.Schemas == null) 260 | { 261 | return; 262 | } 263 | var schemaNames = new HashSet(); 264 | // Walk the schemas looking for imports of other schemas 265 | var schemasToProcess = doc.Schemas 266 | .SelectMany(e => e.Value.Elements(XsdSchemaNamespace + "import")) 267 | .Where(e => e != null && e.Attribute("schemaLocation") != null) 268 | .Select(i => new 269 | { 270 | TargetNamespace = i.Attribute("namespace")?.Value, 271 | SchemaLocation = i.Attribute("schemaLocation")?.Value, 272 | Type = "import", 273 | SchemaDirectory = Directory.GetCurrentDirectory() 274 | }) 275 | .ToList(); 276 | 277 | //Adding includes in 278 | schemasToProcess.AddRange(doc.Schemas 279 | .SelectMany(e => e.Value.Elements(XsdSchemaNamespace + "include")) 280 | .Where(e => e != null && e.Attribute("schemaLocation") != null) 281 | .Select(i => new 282 | { 283 | TargetNamespace = i.Parent.Attribute("namespace")?.Value, 284 | SchemaLocation = i.Attribute("schemaLocation")?.Value, 285 | Type = "include", 286 | SchemaDirectory = Directory.GetCurrentDirectory() 287 | }) 288 | .ToList()); 289 | //Includes and imports removed from schemas 290 | 291 | schemasToProcess.ForEach(i => schemaNames.Add(i.SchemaLocation)); 292 | 293 | foreach (var item in doc.Schemas) 294 | { 295 | item.Value.Elements(XsdSchemaNamespace + "include").Remove(); 296 | item.Value.Elements(XsdSchemaNamespace + "import").Remove(); 297 | } 298 | // Resolve the schemas and add to existing ones 299 | while (schemasToProcess.Count > 0) 300 | { 301 | var import = schemasToProcess.First(); 302 | 303 | var realSchemaDirectory = import.SchemaLocation != string.Empty 304 | ? import.SchemaLocation 305 | : Path.GetDirectoryName(Path.GetFullPath(Path.Join(import.SchemaDirectory, import.SchemaLocation))); 306 | 307 | schemasToProcess.Remove(import); 308 | XmlSchema xmlSchema; 309 | 310 | logger.Informational("XsdImportInclude", string.Format( 311 | CommonResources.XsdImport, 312 | import.SchemaLocation, 313 | import.TargetNamespace)); 314 | 315 | string schemaText = string.Empty; 316 | 317 | schemaText = await GetStringDocumentFromUri(logger, import.SchemaLocation); 318 | 319 | xmlSchema = GetXmlSchema(schemaText, logger); 320 | var includesToRemove = new List(); 321 | var importsToAdd = new HashSet(); 322 | 323 | foreach (XmlSchemaExternal item in xmlSchema.Includes) 324 | { 325 | if (item is XmlSchemaImport || item is XmlSchemaInclude) 326 | { 327 | var schemaLocation = item.SchemaLocation; 328 | 329 | if (!schemaNames.Contains(item.SchemaLocation)) 330 | { 331 | var xmlTargetNamespace = xmlSchema.TargetNamespace; 332 | string itemType; 333 | 334 | if (item is XmlSchemaImport importItem) 335 | { 336 | logger.Informational("import"); 337 | itemType = "import"; 338 | xmlTargetNamespace = importItem.Namespace; 339 | } 340 | else 341 | { 342 | logger.Informational("include"); 343 | itemType = "include"; 344 | } 345 | 346 | //All new imports are added 347 | importsToAdd.Add(xmlTargetNamespace); 348 | schemaNames.Add(item.SchemaLocation); 349 | 350 | var newSchemaToProcess = new 351 | { 352 | TargetNamespace = xmlTargetNamespace, 353 | SchemaLocation = schemaLocation, 354 | Type = itemType, 355 | SchemaDirectory = realSchemaDirectory 356 | }; 357 | 358 | schemasToProcess.Add(newSchemaToProcess); 359 | logger.Informational( 360 | @$"SchemaLocation: {newSchemaToProcess.SchemaLocation}, 361 | SchemaDirectory: {newSchemaToProcess.SchemaDirectory}"); 362 | } 363 | 364 | if (item is XmlSchemaImport) 365 | { 366 | item.SchemaLocation = null; 367 | } 368 | 369 | includesToRemove.Add(item); 370 | } 371 | else 372 | { 373 | throw new WsdlDocumentException(CommonResources.SchemaOnlyAllowsIncludeOrImport); 374 | } 375 | } 376 | 377 | includesToRemove.ForEach(x => xmlSchema.Includes.Remove(x)); 378 | 379 | var sw = new StringWriter(); 380 | xmlSchema.Write(sw); 381 | schemaText = sw.ToString(); 382 | 383 | var schemaElement = XElement.Parse(schemaText, LoadOptions.SetLineInfo); 384 | //BEGIN track schema comment 385 | schemaElement.AddFirst(new XComment(string.Format(CommonResources.XsdImportBegin, import.SchemaLocation))); 386 | schemaElement.Add(new XComment(string.Format(CommonResources.XsdImportEnd, import.SchemaLocation))); 387 | //END track schema comment 388 | XNamespace targetNamespace = import.TargetNamespace ?? GetTargetNamespace(schemaElement); 389 | 390 | if (doc.Schemas.ContainsKey(targetNamespace)) 391 | { 392 | XElement existingSchema = doc.Schemas[targetNamespace]; 393 | var existingSchemaXmlns = existingSchema.Attribute("xmlns")?.Value; 394 | var schemaelementXmlns = schemaElement.Attribute("xmlns")?.Value; 395 | 396 | if (existingSchemaXmlns != null && schemaelementXmlns != null && !existingSchemaXmlns.Equals(schemaelementXmlns)) 397 | { 398 | if (existingSchema.HasElements) 399 | throw new WsdlDocumentException( 400 | $"The xmlns attribute is not the same between schemas with targetNamespace {targetNamespace.NamespaceName}"); 401 | 402 | existingSchema.Parent.Element(existingSchema.Name).Remove(); 403 | doc.Schemas[targetNamespace] = schemaElement; 404 | } 405 | else 406 | { 407 | MergeSchemas(existingSchema, new List() { schemaElement }); 408 | } 409 | } 410 | else 411 | { 412 | doc.Schemas.Add(targetNamespace, schemaElement); 413 | 414 | } 415 | importsToAdd.Remove(targetNamespace.NamespaceName); 416 | 417 | if (doc.Imports.ContainsKey(targetNamespace)) 418 | { 419 | doc.Imports[targetNamespace].UnionWith(importsToAdd); 420 | } 421 | else 422 | { 423 | doc.Imports[targetNamespace] = importsToAdd; 424 | } 425 | } 426 | } 427 | 428 | /// 429 | /// Get string document from uri (URL or path) 430 | /// 431 | /// 432 | /// 433 | /// string document 434 | private static async Task GetStringDocumentFromUri(ILog logger, string location) 435 | { 436 | string documentText; 437 | //We need to check if is URL or a File location 438 | var result = Uri.TryCreate(location, UriKind.Absolute, out var uriResult) 439 | && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); 440 | 441 | if (result) 442 | { 443 | var clientHandler = new HttpClientHandler(); 444 | clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; 445 | HttpResponseMessage response = null; 446 | 447 | using (var httpClient = new HttpClient(clientHandler)) 448 | { 449 | var uri = new Uri(location, UriKind.RelativeOrAbsolute); 450 | 451 | try 452 | { 453 | response = await httpClient.GetAsync(uri); 454 | 455 | documentText = await response.Content.ReadAsStringAsync(); 456 | 457 | if (response.StatusCode != System.Net.HttpStatusCode.OK) 458 | { 459 | // NOTE(daviburg): when the status code was failed, the return string if one is an error message rather than the schema. 460 | logger.Error("FailedToImport", string.Format( 461 | CommonResources.FailedToImport, 462 | uri.OriginalString, 463 | response.StatusCode, 464 | documentText)); 465 | 466 | throw new Exception("Failed to import schema from external url"); 467 | } 468 | } 469 | catch (InvalidOperationException ex) 470 | { 471 | // NOTE(daviburg): this can happen when the content type header charset value of the response is invalid. 472 | logger.Error("FailedToImport", string.Format( 473 | CommonResources.FailedToParseImportedSchemaResponse, 474 | uri.OriginalString, 475 | response.StatusCode, 476 | nameof(InvalidOperationException), 477 | ex.StackTrace)); 478 | throw; 479 | } 480 | catch (HttpRequestException ex) 481 | { 482 | logger.Error("FailedToImport from external url", string.Format( 483 | CommonResources.FailedToImport, 484 | uri.OriginalString, 485 | nameof(HttpRequestException), 486 | ex.StackTrace)); 487 | throw; 488 | } 489 | catch (Exception ex) 490 | { 491 | logger.Error("FailedToImport from external url", string.Format( 492 | CommonResources.FailedToImport, 493 | uri.OriginalString, 494 | nameof(Exception), 495 | ex.StackTrace)); 496 | throw; 497 | } 498 | } 499 | } 500 | else 501 | { 502 | var importLocation = Path.IsPathRooted(location) ? location : Path.Join(Directory.GetCurrentDirectory(), location); 503 | documentText = File.ReadAllText(importLocation); 504 | } 505 | 506 | return documentText; 507 | } 508 | 509 | /// 510 | /// Add namespaces to documentElement. 511 | /// Then, It changes newElements attributes that have prefixes. 512 | /// 513 | /// XElement where the method will add New namespaces 514 | /// List of XElements where attributes value are going to change if have prefixes 515 | /// Namespaces of the newElements 516 | private static void AddXmlnsAndChangePrefixReferenced( 517 | XElement documentElement, 518 | IEnumerable newElements, 519 | Dictionary namespaces) 520 | { 521 | var parentNamespaces = documentElement 522 | .Attributes() 523 | .Where(a => a.ToString() 524 | .Contains("xmlns:")) 525 | .Select(a => new 526 | { 527 | Prefix = a.Name.LocalName, 528 | Namespace = a.Value 529 | }).ToDictionary(a => a.Namespace, a => a.Prefix); 530 | 531 | foreach (var item in namespaces) 532 | { 533 | //string prefix = string.Empty; 534 | parentNamespaces.TryGetValue(item.Key, out string prefix); 535 | 536 | if (prefix == null) 537 | { 538 | prefix = GenerateNewNamespace(documentElement, parentNamespaces, item); 539 | } 540 | 541 | //Modify attributes from elements with the same prefix 542 | var prefixValue = item.Value + ":"; 543 | 544 | foreach (var element in newElements.DescendantsAndSelf()) 545 | { 546 | //Go through all attributes and modify if they have the prefix 547 | var attributes = element 548 | .Attributes() 549 | .Where(e => e.Value.Contains(prefixValue)); 550 | 551 | foreach (var attribute in attributes) 552 | { 553 | if (attribute.Value.Count(i => i == ':') == 1 554 | && !(Uri.TryCreate(attribute.Value, UriKind.Absolute, out var uriResult) 555 | && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps))) 556 | { 557 | var splitValue = attribute.Value.Split(':'); 558 | attribute.Value = prefix + ":" + splitValue[1]; 559 | } 560 | } 561 | } 562 | } 563 | } 564 | 565 | /// 566 | /// It generates a new xmlns:prefix and add it to documentElement 567 | /// 568 | /// XElement to add new xmlns 569 | /// All namespaces of XElement 570 | /// Namespace, prefix KeyValuepair 571 | /// 572 | private static string GenerateNewNamespace( 573 | XElement documentElement, 574 | Dictionary parentNamespaces, 575 | KeyValuePair item) 576 | { 577 | var newNamespaces = parentNamespaces.Values.Where(v => v.Contains(WsdlDocument.DefaultPrefix)); 578 | var initialValue = 1; 579 | 580 | if (newNamespaces.Any()) 581 | { 582 | initialValue = newNamespaces.Select(i => i.Substring(2)).Max(i => int.Parse(i)) + 1; 583 | } 584 | 585 | var newPrefix = DefaultPrefix + initialValue.ToString(); 586 | documentElement.Add(new XAttribute(XNamespace.Xmlns + newPrefix, item.Key)); 587 | parentNamespaces.Add(item.Key, newPrefix); 588 | 589 | return newPrefix; 590 | } 591 | 592 | /// 593 | /// Change WSDL elements to Parent targetNamespace/Prefix 594 | /// 595 | /// 596 | /// Wsdl merged 597 | private static void ChangeElementsToParentTargetNamespace(WsdlDocument doc, XElement documentElement) 598 | { 599 | //Searching for wsdl:portType and getting all the inputs, outputs and faults 600 | var prefixParentNamespace = documentElement.GetPrefixOfNamespace(documentElement.Attribute("targetNamespace").Value); 601 | var operationChildren = documentElement 602 | .Elements(doc.WsdlNamespace + "portType") 603 | .Elements(doc.WsdlNamespace + "operation") 604 | .Elements() 605 | .Where(e => e.Name.LocalName.Equals("input") 606 | || e.Name.LocalName.Equals("output") 607 | || e.Name.LocalName.Equals("fault")); 608 | 609 | foreach (var item in operationChildren) 610 | { 611 | var attribute = item.Attribute("message"); 612 | 613 | if (attribute != null 614 | && attribute.Value.Count(i => i == ':') == 1 615 | && !(Uri.TryCreate(attribute.Value, UriKind.Absolute, out var uriResult) 616 | && (uriResult.Scheme == Uri.UriSchemeHttp 617 | || uriResult.Scheme == Uri.UriSchemeHttps))) 618 | { 619 | var splitValue = attribute.Value.Split(':'); 620 | attribute.Value = prefixParentNamespace + ":" + splitValue[1]; 621 | } 622 | } 623 | 624 | //Searching for binding/type 625 | var bindingsType = documentElement.Elements(doc.WsdlNamespace + "binding"); 626 | 627 | foreach (var item in bindingsType) 628 | { 629 | var attribute = item.Attribute("type"); 630 | 631 | if (attribute != null 632 | && attribute.Value.Count(i => i == ':') == 1 633 | && !(Uri.TryCreate(attribute.Value, UriKind.Absolute, out var uriResult) 634 | && (uriResult.Scheme == Uri.UriSchemeHttp 635 | || uriResult.Scheme == Uri.UriSchemeHttps))) 636 | { 637 | var splitValue = attribute.Value.Split(':'); 638 | attribute.Value = prefixParentNamespace + ":" + splitValue[1]; 639 | } 640 | } 641 | } 642 | 643 | private static void MergeSchemas(XElement schema, IList schemas) 644 | { 645 | foreach (XElement dupSchema in schemas) 646 | { 647 | foreach (XAttribute attribute in dupSchema.Attributes()) 648 | { 649 | var schemaAttribute = schema.Attribute(attribute.Name); 650 | 651 | if (schemaAttribute == null) 652 | { 653 | schema.Add(new XAttribute(attribute.Name, attribute.Value)); 654 | } 655 | else 656 | { 657 | if (schemaAttribute.Name.LocalName.Equals(attribute.Name.LocalName) && 658 | !schemaAttribute.Value.Equals(attribute.Value)) 659 | { 660 | AddXmlnsAndChangePrefixReferenced( 661 | schema, 662 | dupSchema.Elements(), 663 | new Dictionary() 664 | { 665 | { attribute.Value, attribute.Name.LocalName } 666 | }); 667 | } 668 | } 669 | } 670 | schema.Add(dupSchema.Elements()); 671 | } 672 | } 673 | 674 | private static WsdlVersionLiteral DetermineVersion(XNamespace wsdlNS) 675 | { 676 | return wsdlNS.NamespaceName switch 677 | { 678 | Wsdl11Namespace => WsdlVersionLiteral.Wsdl11, 679 | Wsdl20Namespace => WsdlVersionLiteral.Wsdl20, 680 | _ => throw new DocumentParsingException(string.Format(CommonResources.UnknownWsdlVersion, wsdlNS.NamespaceName)) 681 | }; 682 | } 683 | 684 | private static XmlSchema GetXmlSchema(string xmlSchema, ILog logger) 685 | { 686 | try 687 | { 688 | if (File.Exists(xmlSchema)) 689 | { 690 | xmlSchema = new StreamReader(xmlSchema).ReadToEnd(); 691 | } 692 | 693 | using (var doc = new StringReader(xmlSchema)) 694 | { 695 | var result = XmlSchema.Read(doc, null); 696 | return result; 697 | } 698 | } 699 | catch (XmlException ex) 700 | { 701 | logger.Error("GetXmlSchema XmlException", ex); 702 | throw; 703 | } 704 | catch (XmlSchemaException ex) 705 | { 706 | logger.Error("GetXmlSchema XmlSchemaException", ex); 707 | throw; 708 | } 709 | } 710 | } 711 | } -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.Common/WsdlDocumentException.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // -------------------------------------------------------------------------- 6 | using System; 7 | 8 | namespace Microsoft.Azure.ApiManagement.WsdlProcessor.Common 9 | { 10 | [Serializable] 11 | public class WsdlDocumentException : Exception 12 | { 13 | public WsdlDocumentException(string message) : base(message) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common; 2 | using System.Threading.Tasks; 3 | 4 | namespace Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App 5 | { 6 | class Program 7 | { 8 | static async Task Main(string[] args) 9 | { 10 | var log = new ConsoleLog(); 11 | 12 | if (args.Length == 2) 13 | { 14 | var xsdDirectory = args[0]; 15 | var outputDirectory = args[1]; 16 | await XmlSchemaDocument.LoadAsync(xsdDirectory, log, outputDirectory); 17 | } 18 | else 19 | { 20 | log.Error("XSD Directory path and output directory should be provided as a parameter of the tool."); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common/XmlSchemaDocument.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using System.Xml; 10 | using System.Xml.Schema; 11 | using Microsoft.Azure.ApiManagement.Common; 12 | 13 | namespace Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common 14 | { 15 | public class XmlSchemaDocument 16 | { 17 | private const string SchemaPath = "/schemas/"; 18 | //private const string NewDirectory = "newdirectory"; 19 | private static Dictionary Schemas { get; set; } 20 | 21 | private static Dictionary PathXmlSchemaPair { get; set; } 22 | 23 | private static Dictionary> PathOrderListSchemas { get; set; } 24 | 25 | private static string DirectoryPath { get; set; } 26 | 27 | public static async Task LoadAsync(string directoryPath, ILog logger, string outputDirectory) 28 | { 29 | directoryPath = Path.IsPathRooted(directoryPath) ? directoryPath : Path.Join(Directory.GetCurrentDirectory(), directoryPath); 30 | DirectoryPath = directoryPath; 31 | //outputDirectory = outputDirectory ?? NewDirectory; 32 | outputDirectory = Path.IsPathRooted(outputDirectory) ? outputDirectory : Path.Join(DirectoryPath, outputDirectory); 33 | Schemas = new Dictionary(); 34 | PathXmlSchemaPair = new Dictionary(); 35 | PathOrderListSchemas = new Dictionary>(); 36 | logger.Informational($"Getting all xsd files from folder {directoryPath}"); 37 | var schemaPaths = Directory.GetFiles(directoryPath, "*.xsd"); 38 | 39 | if (!schemaPaths.Any()) 40 | { 41 | logger.Error($"No xsd files in folder {directoryPath}"); 42 | return; 43 | } 44 | 45 | if (Directory.Exists(outputDirectory) && Directory.GetFiles(outputDirectory).Length > 0) 46 | { 47 | logger.Error($"{outputDirectory} directory should not have files before executing the tool."); 48 | return; 49 | } 50 | else if (!Directory.Exists(outputDirectory)) 51 | { 52 | Directory.CreateDirectory(outputDirectory); 53 | } 54 | 55 | logger.Informational($"Generating new names for schemas"); 56 | GenerateNewNameForSchemas(schemaPaths, logger); 57 | 58 | logger.Informational($"Starting process of xsd files"); 59 | await ProcessXsdImportsIncludes(schemaPaths, logger); 60 | 61 | //new xsd files 62 | logger.Informational($"Generating new files in {outputDirectory}"); 63 | 64 | foreach (var xmlFile in PathXmlSchemaPair.Keys) 65 | { 66 | logger.Informational($"Generating new file for {xmlFile}"); 67 | var newSchemaFile = PathXmlSchemaPair[xmlFile]; 68 | var file = new FileStream(Path.Join(outputDirectory, Schemas[xmlFile] + ".xsd"), 69 | FileMode.Create, 70 | FileAccess.ReadWrite); 71 | 72 | var xwriter = new XmlTextWriter(file, new UTF8Encoding()) 73 | { 74 | Formatting = System.Xml.Formatting.Indented 75 | }; 76 | 77 | newSchemaFile.Write(xwriter); 78 | logger.Informational($"File generated {Path.GetFileName(file.Name)}"); 79 | } 80 | 81 | var outputDictionary = new Dictionary(); 82 | PathOrderListSchemas 83 | .OrderByDescending(x => x.Value.Count) 84 | .SelectMany(x => x.Value) 85 | .ToList() 86 | .ForEach(item => outputDictionary[Path.GetFileName(item)] = Schemas[item]); 87 | 88 | logger.Informational("Generating upload-plan.json file"); 89 | var uploadPlan = JsonConvert.SerializeObject(outputDictionary, Newtonsoft.Json.Formatting.Indented); 90 | File.WriteAllText(Path.Join(outputDirectory, "upload-plan.json"), uploadPlan); 91 | } 92 | 93 | /// 94 | /// Process all XSD Imports and Includes 95 | /// 96 | /// doc.Schemas where all the imports are added 97 | /// 98 | /// 99 | private static async Task ProcessXsdImportsIncludes(string[] schemaPaths, ILog logger) 100 | { 101 | var visitedSchemas = new HashSet(); 102 | 103 | foreach (var item in schemaPaths) 104 | { 105 | if (!visitedSchemas.Contains(item)) 106 | { 107 | logger.Informational($"Processing parent {Path.GetFileName(item)} schema file."); 108 | var orderedListOfSchemas = new List(); 109 | 110 | if (!(await FindOrder(item, new HashSet(), new HashSet(), orderedListOfSchemas, logger))) 111 | { 112 | throw new InvalidOperationException($"There was an error trying to process {item}"); 113 | } 114 | else 115 | { 116 | PathOrderListSchemas[item] = orderedListOfSchemas; 117 | orderedListOfSchemas.ForEach(i => visitedSchemas.Add(i)); 118 | } 119 | } 120 | logger.Informational($"Schema file {Path.GetFileName(item)} is already processed."); 121 | } 122 | } 123 | 124 | /// 125 | /// Fill orderedListOfSchemas keeping the independent schemas at the beginning 126 | /// and the dependent schemas at the end 127 | /// 128 | /// 129 | /// 130 | /// 131 | /// 132 | /// 133 | /// True if there is no problem processing. False if there is a circular dependency or a Redefine element in schema 134 | private async static Task FindOrder( 135 | string schemaLocation, 136 | HashSet importedNamespaces, 137 | HashSet visitedNamespaces, 138 | IList orderedListOfSchemas, 139 | ILog logger) 140 | { 141 | logger.Informational($"Processing {Path.GetFileName(schemaLocation)} schema file."); 142 | 143 | if (importedNamespaces.Contains(schemaLocation)) 144 | { 145 | logger.Error($"There is a circular dependency in the xml schemas. {Path.GetFileName(schemaLocation)} is in a cycle of schema dependencies"); 146 | return false; 147 | } 148 | 149 | if (visitedNamespaces.Contains(schemaLocation)) 150 | { 151 | logger.Informational($"Already visited {schemaLocation}"); 152 | return true; 153 | } 154 | 155 | var documentText = await GetStringDocumentFromPathAsync(schemaLocation); 156 | var xmlSchema = GetXmlSchema(documentText, logger); 157 | PathXmlSchemaPair[schemaLocation] = xmlSchema; 158 | 159 | importedNamespaces.Add(schemaLocation); 160 | visitedNamespaces.Add(schemaLocation); 161 | logger.Informational("Processing Imports and Includes"); 162 | 163 | foreach (XmlSchemaExternal element in xmlSchema.Includes) 164 | { 165 | string location = string.Empty; 166 | 167 | if (element is XmlSchemaImport || element is XmlSchemaInclude) 168 | { 169 | location = Path.IsPathRooted(element.SchemaLocation) ? element.SchemaLocation : Path.Join(DirectoryPath, element.SchemaLocation); 170 | element.SchemaLocation = NormalizeWellFormedArmSchema(location, logger); 171 | } 172 | else 173 | { 174 | logger.Error($"Redefine is not allowed in the tool."); 175 | return false; 176 | } 177 | 178 | if (!(await FindOrder(location, importedNamespaces, visitedNamespaces, orderedListOfSchemas, logger))) 179 | { 180 | return false; 181 | } 182 | } 183 | 184 | orderedListOfSchemas.Add(schemaLocation); 185 | importedNamespaces.Remove(schemaLocation); 186 | logger.Informational($"End of processing {Path.GetFileName(schemaLocation)} schema file."); 187 | 188 | return true; 189 | } 190 | 191 | private static void GenerateNewNameForSchemas(string schemaPaths, ILog logger) 192 | { 193 | GenerateNewNameForSchemas(new string[] { schemaPaths }, logger); 194 | } 195 | 196 | /// 197 | /// Generates new name for schemas 198 | /// e.g. foo.xsd -> foo, foo_1.xsd -> foo-1, foo_1_2.xsd -> foo-1-2 199 | /// 200 | /// 201 | /// 202 | /// 203 | private static void GenerateNewNameForSchemas(string[] schemaPaths, ILog logger) 204 | { 205 | foreach (var item in schemaPaths) 206 | { 207 | var schemaNameWithoutExtension = Path.GetFileNameWithoutExtension(item); 208 | logger.Informational($"Generating new name for {schemaNameWithoutExtension}.xsd"); 209 | var rgx = new Regex("[^a-zA-Z0-9 -]"); 210 | Schemas[item] = rgx.Replace(schemaNameWithoutExtension, "-"); 211 | logger.Informational($"New name for {schemaNameWithoutExtension} -> {Schemas[item]}"); 212 | } 213 | } 214 | 215 | /// 216 | /// Get string document from uri (URL or path) 217 | /// 218 | /// 219 | /// string document 220 | private static async Task GetStringDocumentFromPathAsync(string location) 221 | { 222 | string documentText; 223 | var importLocation = Path.IsPathRooted(location) ? location : Path.Join(DirectoryPath, location); 224 | documentText = await File.ReadAllTextAsync(importLocation); 225 | 226 | return documentText; 227 | } 228 | 229 | /// 230 | /// Gets the new name for schemas and generates a new location for targetnamespace in Imports and Includes 231 | /// 232 | /// 233 | /// 234 | /// 235 | private static string NormalizeWellFormedArmSchema(string schema, ILog logger) 236 | { 237 | Schemas.TryGetValue(schema, out var schemaNewName); 238 | 239 | if (string.IsNullOrEmpty(schemaNewName)) 240 | { 241 | logger.Warning($"No new name found for {schema}"); 242 | GenerateNewNameForSchemas(schema, logger); 243 | schemaNewName = Schemas[schema]; 244 | } 245 | 246 | return string.Concat(SchemaPath, schemaNewName); 247 | } 248 | 249 | private static XmlSchema GetXmlSchema(string xmlSchema, ILog logger) 250 | { 251 | try 252 | { 253 | using (var doc = new StringReader(xmlSchema)) 254 | { 255 | var result = XmlSchema.Read(doc, null); 256 | 257 | if (string.IsNullOrEmpty(result.TargetNamespace)) 258 | { 259 | var error = $"{xmlSchema} does not have targetNamespace attribute"; 260 | logger.Error(error); 261 | throw new NullReferenceException(error); 262 | } 263 | 264 | return result; 265 | } 266 | } 267 | catch (XmlException e) 268 | { 269 | logger.Error($"{e.Message}"); 270 | logger.Error($"Location {xmlSchema} contains invalid xml: {e.StackTrace}"); 271 | throw; 272 | } 273 | catch (XmlSchemaException e) 274 | { 275 | logger.Error($"{e.Message}"); 276 | logger.Error($"Location {xmlSchema} contains invalid xml: {e.StackTrace}"); 277 | throw; 278 | } 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Always 15 | 16 | 17 | Always 18 | 19 | 20 | Always 21 | 22 | 23 | Always 24 | 25 | 26 | Always 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.ApiManagement.XmlSchemaProcessor.Common; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | 5 | namespace Microsoft.Azure.ApiManagement.XmlSchemaProcessor.TestConsole 6 | { 7 | public class Program 8 | { 9 | static async Task Main(string[] args) 10 | { 11 | var log = new ConsoleLog(); 12 | var directoryPath = @"C:\proj\GMFiles\XSD with Include\GetProvideShipments"; 13 | await XmlSchemaDocument.LoadAsync(directoryPath, log, Path.Combine(directoryPath, "myoutput")); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/TestConsole/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.ApiManagement.WsdlProcessor.Common; 2 | using System; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | using System.Xml.Linq; 6 | 7 | namespace TestConsole 8 | { 9 | class Program 10 | { 11 | static async Task Main(string[] args) 12 | { 13 | var log = new ConsoleLog(); 14 | var wsdlfile = "API-0427"; 15 | var wsdlString = File.ReadAllText(wsdlfile + ".wsdl"); 16 | var xDocument = XDocument.Parse(wsdlString); 17 | await WsdlDocument.LoadAsync(xDocument.Root, log); 18 | //WsdlDocument.DumpInvalidNodes(xDocument.Root); 19 | xDocument.Root.Save(wsdlfile + "-processed.wsdl"); 20 | //FileStream fs = new FileStream(@"C:\Temp\" + wsdlfile + "-processed.wsdl", FileMode.Create); 21 | //wsdlDocument.Save(XmlWriter.Create(fs, new XmlWriterSettings() { Indent = true })); 22 | //fs.Close(); 23 | Console.ReadLine(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/TestConsole/TestConsole.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Always 16 | 17 | 18 | Always 19 | 20 | 21 | Always 22 | 23 | 24 | Always 25 | 26 | 27 | Always 28 | 29 | 30 | Always 31 | 32 | 33 | Always 34 | 35 | 36 | Always 37 | 38 | 39 | Always 40 | 41 | 42 | Always 43 | 44 | 45 | Always 46 | 47 | 48 | Always 49 | 50 | 51 | Always 52 | 53 | 54 | Always 55 | 56 | 57 | Always 58 | 59 | 60 | Always 61 | 62 | 63 | Always 64 | 65 | 66 | Always 67 | 68 | 69 | Always 70 | 71 | 72 | Always 73 | 74 | 75 | Always 76 | 77 | 78 | Always 79 | 80 | 81 | Always 82 | 83 | 84 | Always 85 | 86 | 87 | Always 88 | 89 | 90 | Always 91 | 92 | 93 | Always 94 | 95 | 96 | Always 97 | 98 | 99 | Always 100 | 101 | 102 | Always 103 | 104 | 105 | Always 106 | 107 | 108 | Always 109 | 110 | 111 | Always 112 | 113 | 114 | Always 115 | 116 | 117 | Always 118 | 119 | 120 | Always 121 | 122 | 123 | Always 124 | 125 | 126 | Always 127 | 128 | 129 | Always 130 | 131 | 132 | Always 133 | 134 | 135 | Always 136 | 137 | 138 | Always 139 | 140 | 141 | Always 142 | 143 | 144 | Always 145 | 146 | 147 | Always 148 | 149 | 150 | Always 151 | 152 | 153 | Always 154 | 155 | 156 | Always 157 | 158 | 159 | Always 160 | 161 | 162 | Always 163 | 164 | 165 | Always 166 | 167 | 168 | Always 169 | 170 | 171 | Always 172 | 173 | 174 | Always 175 | 176 | 177 | Always 178 | 179 | 180 | Always 181 | 182 | 183 | Always 184 | 185 | 186 | Always 187 | 188 | 189 | Always 190 | 191 | 192 | Always 193 | 194 | 195 | Always 196 | 197 | 198 | Always 199 | 200 | 201 | Always 202 | 203 | 204 | Always 205 | 206 | 207 | Always 208 | 209 | 210 | Always 211 | 212 | 213 | Always 214 | 215 | 216 | Always 217 | 218 | 219 | Always 220 | 221 | 222 | Always 223 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /ApiManagementSchemaImport/batchWsdlProcessor.ps1: -------------------------------------------------------------------------------- 1 | param ([Parameter(Mandatory)]$configFile, [Parameter(Mandatory)]$apimresource, [Parameter(Mandatory)]$wsdlProcessor) 2 | #$apimResource = "https://management.apim.net/subscriptions/a200340d-6b82-494d-9dbf-687ba6e33f9e/resourceGroups/devenv/providers/Microsoft.ApiManagement/service/devenv" 3 | #$configFile = "" 4 | Write-Output "Starting Azure login" 5 | az login 6 | Write-Output "Starting the process" 7 | $ErrorActionPreference = "Stop" 8 | $token = az account get-access-token | ConvertFrom-Json 9 | $bearer =$token.accessToken 10 | $headers = @{Authorization = "Bearer $bearer"} 11 | 12 | Write-Output "Reading file $configFile" 13 | $json = (Get-Content -Path $configFile -Raw) | ConvertFrom-Json 14 | $counter = 1 15 | $json.psobject.properties | ForEach-Object { 16 | $directory = $_.Value 17 | $wsdlFile = $_.Name 18 | Set-Location $directory 19 | $fileOutput = "new-" + $wsdlFile 20 | & $wsdlProcessor $wsdlFile $fileOutput 21 | $content = Get-Content -Path $fileOutput -Raw -Encoding utf8 22 | $apiName = "test" + $counter 23 | Write-Output "Api name: $apiName" 24 | $uri = "$apimResource/apis/" + $apiName + "?import=true&api-version=2021-01-01-preview" 25 | Write-Output "Calling $uri" 26 | $res = iwr -UseBasicParsing -Method Put -Headers $headers -Uri $uri -ContentType "application/json; charset=utf-8" -Body (@{ "id"="/apis/$apiName"; "name"="$apiName" ; "properties" = @{ "format" = "wsdl"; "value" = "$content"; "displayName"="$apiName"; "protocols"=@("https"); "path"="$apiName"}; } | ConvertTo-Json) 27 | if (($res.StatusCode -ne 200) -and ($res.StatusCode -ne 201) -and ($res.StatusCode -ne 202)) 28 | { 29 | Throw "Request returned with HTTP code $req.StatusCode" 30 | } 31 | $counter = $counter + 1 32 | } 33 | 34 | Write-Output "Process successfully ended" 35 | #Now we upload the file 36 | #$res = iwr -UseBasicParsing -Method Put -Headers $headers -Uri $uri -ContentType "application/json; charset=utf-8" -Body (@{ "id"="/apis/test2"; "name"="test2" ; "properties" = @{ "format" = "wsdl"; "value" = "$content"; "displayName"="test1"; "protocols"=@("https"); "path"="test2"}; } | ConvertTo-Json) -------------------------------------------------------------------------------- /ApiManagementSchemaImport/batchXmlSchemaProcessor.ps1: -------------------------------------------------------------------------------- 1 | param ([Parameter(Mandatory)]$configFile, [Parameter(Mandatory)]$apimresource, [Parameter(Mandatory)]$xmlProcessor) 2 | #$apimResource = "https://management.apim.net/subscriptions/a200340d-6b82-494d-9dbf-687ba6e33f9e/resourceGroups/devenv/providers/Microsoft.ApiManagement/service/devenv" 3 | #$configFile = "" 4 | Write-Output "Starting Azure login" 5 | az login 6 | Write-Output "Starting the process" 7 | $ErrorActionPreference = "Stop" 8 | $token = az account get-access-token | ConvertFrom-Json 9 | $bearer =$token.accessToken 10 | $headers = @{Authorization = "Bearer $bearer"} 11 | 12 | Write-Output "Reading file $configFile" 13 | $json = (Get-Content -Path $configFile -Raw) | ConvertFrom-Json 14 | $json.psobject.properties | ForEach-Object { 15 | $inputDirectory = $_.Name 16 | $outputDirectory = $_.Value 17 | Write-Output "Input directory: $inputDirectory" 18 | Write-Output "Output directory: $outputDirectory" 19 | Set-Location $inputDirectory 20 | & $xmlProcessor $inputDirectory $outputDirectory 21 | $file = Join-Path -Path $outputDirectory -ChildPath "upload-plan.json" 22 | $jsonXml = (Get-Content -Path $file -Raw) | ConvertFrom-Json 23 | 24 | $jsonXml.psobject.properties | ForEach-Object { 25 | $childPath = $_.Value + ".xsd" 26 | $schema = Join-Path -Path $outputDirectory -ChildPath $childPath 27 | $uri = $apimresource + "/schemas/" + $_.Value + "?api-version=2021-04-01-preview" 28 | Write-Output "Reading $schema" 29 | $content = Get-Content -Path $schema -Raw -Encoding utf8 30 | Write-Output "Updating schema to $uri" 31 | $res = iwr -UseBasicParsing -Method Put -Headers $headers -Uri $uri -ContentType "application/json; charset=utf-8" ` 32 | -Body (@{ ` 33 | "properties" = @{ ` 34 | "schemaType" = "xml"; ` 35 | "value" = "$content"; ` 36 | }; ` 37 | } | ConvertTo-Json) 38 | if (($res.StatusCode -ne 200) -and ($res.StatusCode -ne 201) -and ($res.StatusCode -ne 202)) 39 | { 40 | Throw "Request returned with HTTP code $req.StatusCode" 41 | } 42 | } 43 | } 44 | 45 | Write-Output "Process successfully ended" 46 | #Now we upload the file 47 | #$res = iwr -UseBasicParsing -Method Put -Headers $headers -Uri $uri -ContentType "application/json; charset=utf-8" -Body (@{ "id"="/apis/test2"; "name"="test2" ; "properties" = @{ "format" = "wsdl"; "value" = "$content"; "displayName"="test1"; "protocols"=@("https"); "path"="test2"}; } | ConvertTo-Json) -------------------------------------------------------------------------------- /ApiManagementSchemaImport/uploadschemas.ps1: -------------------------------------------------------------------------------- 1 | param ([Parameter(Mandatory)]$file, [Parameter(Mandatory)]$apimresource) 2 | Write-Output "Starting Azure login" 3 | az login 4 | Write-Output "Starting the process" 5 | $ErrorActionPreference = "Stop" 6 | $token = az account get-access-token | ConvertFrom-Json 7 | $bearer =$token.accessToken 8 | $headers = @{Authorization = "Bearer $bearer"} 9 | 10 | $directoryPath = Split-Path -Path $file 11 | Write-Output "Reading file $file" 12 | $json = (Get-Content -Path $file -Raw) | ConvertFrom-Json 13 | 14 | $json.psobject.properties | ForEach-Object { 15 | $childPath = $_.Value + ".xsd" 16 | $schema = Join-Path -Path $directoryPath -ChildPath $childPath 17 | $uri = $apimresource + "/schemas/" + $_.Value + "?api-version=2021-04-01-preview" 18 | Write-Output "Reading $schema" 19 | $content = Get-Content -Path $schema -Raw -Encoding utf8 20 | Write-Output "Updating schema to $uri" 21 | $res = iwr -UseBasicParsing -Method Put -Headers $headers -Uri $uri -ContentType "application/json; charset=utf-8" ` 22 | -Body (@{ ` 23 | "properties" = @{ ` 24 | "schemaType" = "xml"; ` 25 | "value" = "$content"; ` 26 | }; ` 27 | } | ConvertTo-Json) 28 | if (($res.StatusCode -ne 200) -and ($res.StatusCode -ne 201) -and ($res.StatusCode -ne 202)) 29 | { 30 | Throw "Request returned with HTTP code $req.StatusCode" 31 | } 32 | } 33 | 34 | Write-Output "Process successfully ended" -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [project-title] Changelog 2 | 3 | 4 | # x.y.z (yyyy-mm-dd) 5 | 6 | *Features* 7 | * ... 8 | 9 | *Bug Fixes* 10 | * ... 11 | 12 | *Breaking Changes* 13 | * ... 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to [project-title] 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 6 | 7 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 14 | 15 | - [Code of Conduct](#coc) 16 | - [Issues and Bugs](#issue) 17 | - [Feature Requests](#feature) 18 | - [Submission Guidelines](#submit) 19 | 20 | ## Code of Conduct 21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | 23 | ## Found an Issue? 24 | If you find a bug in the source code or a mistake in the documentation, you can help us by 25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Want a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | 33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 34 | 35 | ## Submission Guidelines 36 | 37 | ### Submitting an Issue 38 | Before you submit an issue, search the archive, maybe your question was already answered. 39 | 40 | If your issue appears to be a bug, and hasn't been reported, open a new issue. 41 | Help us to maximize the effort we can spend fixing issues and adding new 42 | features, by not reporting duplicate issues. Providing the following information will increase the 43 | chances of your issue being dealt with quickly: 44 | 45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 46 | * **Version** - what version is affected (e.g. 0.1.2) 47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 48 | * **Browsers and Operating System** - is this a problem with all browsers? 49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps 50 | * **Related Issues** - has a similar issue been reported before? 51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be 52 | causing the problem (line of code or commit) 53 | 54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new]. 55 | 56 | ### Submitting a Pull Request (PR) 57 | Before you submit your Pull Request (PR) consider the following guidelines: 58 | 59 | * Search the repository (https://github.com/[organization-name]/[repository-name]/pulls) for an open or closed PR 60 | that relates to your submission. You don't want to duplicate effort. 61 | 62 | * Make your changes in a new git fork: 63 | 64 | * Commit your changes using a descriptive commit message 65 | * Push your fork to GitHub: 66 | * In GitHub, create a pull request 67 | * If we suggest changes then: 68 | * Make the required updates. 69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 70 | 71 | ```shell 72 | git rebase master -i 73 | git push -f 74 | ``` 75 | 76 | That's it! Thank you for your contribution! 77 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # API Management schema import tools 2 | 3 | This repository contains the source code for several tools that are useful to prepare and upload WSDL and XML schema files for use in your [Azure API Management](https://azure.microsoft.com/services/api-management/) service instance: 4 | 5 | - **WSDLProcessor**: Takes a WSDL file as an input and outputs another WSDL file with references through `wsdl:import`, `xsd:import`, and `xsd:include` resolved and merged inline. The references are resolved from the local filesystem or through a URL. 6 | - **XMLSchemaProcessor**: Takes a folder with XSD files, renames them based on Azure Resource Manager naming requirements, and creates a sequence to upload those schemas into Azure API Management based on a schema dependency graph 7 | - **PowerShell tools** 8 | - **uploadschemas.ps1**: Uploads the XSD schema files generated by the XMLSchemaProcessor to your Azure API Management service 9 | - **batchWsdlProcessor.ps1**: Runs WSDLProcessor on all WSDL files with location specified in a JSON file and uploads the generated WSDL files into your Azure API Management service 10 | - **batchXmlSchemaProcessor.ps1**: Runs XMLSchemaProcessor for all folders listed in a JSON file and uploads the generated XSD schemas into your Azure API Management service 11 | 12 | ## Features 13 | 14 | ### WSDLProcessor 15 | 16 | This project framework provides the following features: 17 | 18 | - Accepts two command-line parameters: 19 | - Path to input WSDL file (required) 20 | - Path to schemaLocation (optional) 21 | - Detects, resolves, and inlines: 22 | - All `wsdl:import` directives 23 | - All `xsd:import` and `xsd:include` elements in XML schemas 24 | - Merges all XML schemas with the same target namespace into a single schema 25 | - Resolves the following types of references: 26 | - HTTP/HTTPS absolute URLs. Any non-`200` response is a failure. 27 | - Absolute local filesystem locations 28 | - Relative local filesystem locations. For the base location, the tool uses the current file location, **not root file location or the location of the tool itself**. 29 | - Outputs a single WSDL file 30 | 31 | ### XMLSchemaProcessor 32 | 33 | This tool provides the following features: 34 | 35 | - Accepts two command-line parameters: 36 | - A folder with all schemas 37 | - Output folder 38 | - Produces a single file upload-plan.json in the output folder 39 | - Performs the following steps: 40 | 41 | - Iterates through all files in the folder with .xsd extension 42 | - Detects all `xsd:import` and `xsd:include` elements 43 | - **Fails immediately if any import or include doesn't have `schemaLocation` or the value is not a local file location** 44 | - For each filename, generates an Azure Resource Manager-compliant resource name: 45 | 46 | - Drops file extension 47 | - Replaces all non-alphanumeric symbols with a single dash 48 | 49 | Examples: foo.xsd -> foo, foo_1.xsd -> foo-1, foo_1_2.xsd -> foo-1-2, etc. 50 | 51 | - Replaces `schemaLocation` with a reference to a well-formed ARM schema resource: foo.xsd -> /schemas/foo, foo_1_2.xsd -> /schemas/foo-1-2 52 | - Builds a dependency graph between all schema files 53 | - Writes a single JSON document in the output file with property names corresponding to filenames and property values corresponding to ARM names in the order of dependency 54 | 55 | Example: If foo.xsd depends on foo_1_2.xsd, upload-plan.json should contain: `{ "foo_1_2.xsd": "foo-1-2", "foo.xsd": "foo" }` 56 | 57 | - Fails on the first error with a descriptive error message written to standard output 58 | 59 | ### PowerShell script to upload generated XML schemas 60 | 61 | The Powershell script **uploadschemas.ps1** provides the following features: 62 | 63 | - Accepts two command-line parameters: 64 | - Location of JSON file generated by schema processing tool (XMLSchemaProcessor) 65 | - API Management resource URL, e.g. `https://management.azure.com/subscriptions/{subid}/resourceGroups/{rgname}/providers/Microsoft.ApiManagement/service/{servicename}` 66 | - Acquires Azure access token for current user 67 | - Iterates through schemas in the source JSON file and uploads them to the API Management service using HTTP calls 68 | - Fails on first error 69 | 70 | ### PowerShell script to generate WSDL merged files and upload them to API Management 71 | 72 | The Powershell script **batchWsdlProcessor.ps1** provides the following features: 73 | 74 | - Accepts three command-line parameters: 75 | - Full path of JSON configuration file with content similar to: 76 | `{"wsdlFileName.wsdl" : "DirectoryPathOfWsdlFile", ...}` 77 | - API Management resource URL, e.g., `https://management.azure.com/subscriptions/{subid}/resourceGroups/{rgname}/providers/Microsoft.ApiManagement/service/{servicename}` 78 | - WSDLProcessor path, e.g., `C:\myPathParent\myPathChild\[...]\Microsoft.Azure.ApiManagement.WsdlProcessor.App.exe` 79 | - Acquires Azure access token for current user 80 | - Iterates through JSON configuration file and generates new WSDL files with merged schemas 81 | - Uploads the new WSDL files to the API Management service using HTTP calls 82 | - Fails on first error 83 | 84 | ### PowerShell script to generate new XML schemas and upload them to API Management 85 | 86 | The Powershell script **batchXmlSchemaProcessor.ps1** provides the following features: 87 | 88 | - Accepts three command-line parameters: 89 | - Full path of JSON configuration file with content similar to: 90 | `{"inputDirectoryWithSchemas" : "OutputDirectory", ...}` 91 | - API Management resource URL, e.g., `https://management.azure.com/subscriptions/{subid}/resourceGroups/{rgname}/providers/Microsoft.ApiManagement/service/{servicename}` 92 | - XMLSchemaProcessor path, e.g. `C:\myPathParent\myPathChild\[...]\Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App.exe` 93 | - Acquires Azure access token for current user 94 | - Iterates through JSON configuration file and generates new XML schema files and an upload-plan.json for each 95 | - Uploads the new XML schema files to the API Management service using the upload-plan.json files and HTTP calls 96 | - Fails on first failure 97 | 98 | ## Getting started 99 | 100 | ### Prerequisites 101 | 102 | - OS: Windows, Linux, macOS 103 | - [.NET 9.0](https://dotnet.microsoft.com/download/dotnet/9.0) 104 | - [.NET CLI](https://docs.microsoft.com//dotnet/core/tools/) 105 | - [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli) 106 | - [PowerShell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell) 107 | 108 | ### Run WSDLProcessor 109 | 110 | 1. When you have the .NET CLI installed on your OS of choice, download the code and go to the Microsoft.Azure.ApiManagement.WsdlProcessor.App directory: 111 | 112 | git clone https://github.com/Azure-Samples/api-management-schema-import.git 113 | 114 | cd api-management-schema-import/ApiManagementSchemaImport/Microsoft.Azure.ApiManagement.WsdlProcessor.App 115 | 116 | 1. Restore the packages that are specified in the .csproj file of the project: 117 | 118 | dotnet restore 119 | 120 | 1. Build the project: 121 | 122 | dotnet build 123 | 124 | This will drop a binary in `./bin/[configuration]/[net9.0]/[Microsoft.Azure.ApiManagement.WsdlProcessor.App.exe]` 125 | 126 | 1. Run the binary: 127 | 1.1. Scenario 1 (with all schemaReference at http URL) 128 | C:\folder\Microsoft.Azure.ApiManagement.WsdlProcessor.App.exe "/mywsdlfile.wsdl" 129 | 130 | 1.2. Scenario 2 (with all schemaReference point to a file) 131 | C:\folder\Microsoft.Azure.ApiManagement.WsdlProcessor.App.exe "/mywsdlfile.wsdl" "" 132 | 133 | ### Run XmlSchemaProcessor 134 | 135 | 1. When you have the .NET CLI installed on your OS of choice, download the code and go to the Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App directory: 136 | 137 | git clone https://github.com/Azure-Samples/api-management-schema-import.git 138 | 139 | cd api-management-schema-import/Mcrosoft.Azure.ApiManagement.XmlSchemaProcessor.App 140 | 141 | 1. Restore the packages that are specified in the .csproj file of the projecgt: 142 | 143 | dotnet restore 144 | 145 | 1. Build the project: 146 | 147 | dotnet build 148 | 149 | This will drop a binary in `./bin/[configuration]/[net9.0]/[Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App.exe]` 150 | 151 | 1. Run the binary: 152 | 153 | c:\folder\Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App.exe "c:\schemaslocation\" "c:\schemaslocation\output\" 154 | 155 | ### Powershell UploadSchemas quickstart 156 | 157 | .\uploadschemas.ps1 "upload-planLocationFile" "https://management.azure.com/subscriptions/{subid}/resourceGroups/{rgname}/providers/Microsoft.ApiManagement/service/{servicename}" 158 | 159 | ### Powershell batchWsdlProcessor quickstart 160 | 161 | .\batchWsdlProcessor.ps1 "C:\myPathParent\myPathChild\...\wsdlFiles.json" "https://management.azure.com/subscriptions/{subid}/resourceGroups/{rgname}/providers/Microsoft.ApiManagement/service/{servicename}" "c:\folder\Microsoft.Azure.ApiManagement.WsdlProcessor.App.exe" 162 | 163 | ### Powershell batchXmlSchemaProcessor quickstart 164 | 165 | .\batchXmlSchemaProcessor.ps1 "C:\myPathParent\myPathChild\...\xmlSchemaFolders.json" "https://management.azure.com/subscriptions/{subid}/resourceGroups/{rgname}/providers/Microsoft.ApiManagement/service/{servicename}" "c:\folder\Microsoft.Azure.ApiManagement.XmlSchemaProcessor.App.exe" 166 | 167 | ## Resources 168 | 169 | * [WSDL Schema Files Specification](https://schemas.xmlsoap.org/wsdl/) 170 | * [API Management REST API](https://docs.microsoft.com/rest/api/apimanagement/current-ga/global-schema) 171 | * [Validation policies in API Management](https://docs.microsoft.com/azure/api-management/validation-policies) 172 | * [API Management schemas for content validation](https://docs.microsoft.com/azure/api-management/validation-policies#schemas-for-content-validation) 173 | -------------------------------------------------------------------------------- /examples/WsdlProcessor/Include.xsd: -------------------------------------------------------------------------------- 1 | 2 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/WsdlProcessor/echoInclude.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 12 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/WsdlProcessor/output.wsdl: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/XmlSchemaProcessor/outputFolder/schema1.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/XmlSchemaProcessor/outputFolder/schema2.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Addresses for International Purchase order schema 6 | Copyright 2000 Example.com. All rights reserved. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/XmlSchemaProcessor/outputFolder/upload-plan.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema2.xsd": "schema2", 3 | "schema1.xsd": "schema1" 4 | } -------------------------------------------------------------------------------- /examples/XmlSchemaProcessor/schema1.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/XmlSchemaProcessor/schema2.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Addresses for International Purchase order schema 5 | Copyright 2000 Example.com. All rights reserved. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/batchWsdlProcessor/configFileWsdl.json: -------------------------------------------------------------------------------- 1 | { 2 | "wsdlFileName1.wsdl" : "C:/myPathParent/myPathChild/", 3 | "wsdlFileName2.wsdl" : "C:/myPathParent/myPathChild/", 4 | "wsdlFileName3.wsdl" : "C:/myPathParent/myPathChild/" 5 | } -------------------------------------------------------------------------------- /examples/batchXmlSchemaProcessor/configFileXml.json: -------------------------------------------------------------------------------- 1 | { 2 | "C:/myPathParent/myPathChild/XmlSchemasFolder1/" : "C:/myPathParent/myPathChild/XmlSchemasFolder1/outputfolder", 3 | "C:/myPathParent/myPathChild/XmlSchemasFolder2/" : "C:/myPathParent/myPathChild/XmlSchemasFolder2/outputfolder", 4 | "C:/myPathParent/myPathChild/XmlSchemasFolder3/" : "C:/myPathParent/myPathChild/XmlSchemasFolder3/outputfolder" 5 | } -------------------------------------------------------------------------------- /examples/uploadSchemas/upload-plan.json: -------------------------------------------------------------------------------- 1 | { 2 | "GetProvideShipments_1.xsd": "GetProvideShipments-1", 3 | "GetProvideShipments.xsd": "GetProvideShipments" 4 | } --------------------------------------------------------------------------------