Skip to content

Commit

Permalink
Add SchemaValidator to validate WiX authoring.
Browse files Browse the repository at this point in the history
SchemaValidator is a quick-n-dirty tool to let you validate a set of WiX
source files against the WiX schemas. This is mostly useful to highlight
incomplete/inaccurate schemas.
  • Loading branch information
barnson committed Dec 21, 2022
1 parent 88ff8c6 commit 32c33f0
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 2 deletions.
9 changes: 7 additions & 2 deletions Web.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33122.133
VisualStudioVersion = 17.4.33103.184
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{C728C975-EEE4-4A54-ACD2-95E8BCA2F5CE}"
Expand All @@ -12,10 +11,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XsdToMarkdownTests", "src\t
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{1D3076DE-5378-4273-AB3B-C14B6F4C46BC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FeedGenerator", "src\FeedGenerator\FeedGenerator.csproj", "{07F578E6-AE83-4615-821D-59B4F8D92B25}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FeedGenerator", "src\FeedGenerator\FeedGenerator.csproj", "{07F578E6-AE83-4615-821D-59B4F8D92B25}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XmlDocToMarkdown", "src\XmlDocToMarkdown\XmlDocToMarkdown.csproj", "{AD1815B0-1F4F-4CEE-961D-0AAFE21227BF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SchemaValidator", "tools\SchemaValidator\SchemaValidator.csproj", "{20D9C939-933C-4F1F-8EF7-298CA16F136F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -42,6 +43,10 @@ Global
{AD1815B0-1F4F-4CEE-961D-0AAFE21227BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD1815B0-1F4F-4CEE-961D-0AAFE21227BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD1815B0-1F4F-4CEE-961D-0AAFE21227BF}.Release|Any CPU.Build.0 = Release|Any CPU
{20D9C939-933C-4F1F-8EF7-298CA16F136F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20D9C939-933C-4F1F-8EF7-298CA16F136F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20D9C939-933C-4F1F-8EF7-298CA16F136F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20D9C939-933C-4F1F-8EF7-298CA16F136F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
97 changes: 97 additions & 0 deletions tools/SchemaValidator/CommandLine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.

namespace WixBuildTools.SchemaValidator;

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

/// <summary>
/// Command-line parsing.
/// </summary>
public class CommandLine
{
private CommandLine()
{
}

/// <summary>
/// List of schema files to process.
/// </summary>
public List<string> Schemas { get; private set; } = new List<string>();

/// <summary>
/// List of source files to process.
/// </summary>
public List<string> Sources { get; private set; } = new List<string>();

/// <summary>
/// Show the help text.
/// </summary>
public static void ShowHelp()
{
Console.WriteLine("SchemaValidator.exe [-?] path/to/*.xsd path/to/*.wx?");
}

/// <summary>
/// Parses the command-line.
/// </summary>
/// <param name="args">Arguments from command-line.</param>
/// <param name="commandLine">Command line object created from command-line arguments</param>
/// <returns>True if command-line is parsed, false if a failure was occurred.</returns>
public static bool TryParseArguments(string[] args, out CommandLine commandLine)
{
var success = true;

commandLine = new CommandLine();

for (var i = 0; i < args.Length; ++i)
{
if ('-' == args[i][0] || '/' == args[i][0])
{
var arg = args[i].Substring(1).ToLowerInvariant();
if ("?" == arg || "help" == arg)
{
return false;
}
}
else
{
var paths = args[i].Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

foreach (var path in paths)
{
var sourcePath = Path.GetFullPath(path);
var sourceDir = Path.GetDirectoryName(sourcePath);
var wildcard = sourcePath.Substring(sourceDir!.Length + 1);
var files = Directory.EnumerateFiles(sourceDir, wildcard, SearchOption.AllDirectories);
if (files.Any())
{
commandLine.Schemas.AddRange(files.Where(f => Path.GetExtension(f).Equals(".xsd", StringComparison.OrdinalIgnoreCase)));
commandLine.Sources.AddRange(files.Where(f => Path.GetExtension(f).StartsWith(".wx", StringComparison.OrdinalIgnoreCase)));
}
else
{
Console.Error.WriteLine($"Source file '{sourcePath}' could not be found.");
success = false;
}
}
}
}

if (0 == commandLine.Schemas.Count)
{
Console.Error.WriteLine("No schema files specified. Specify at least one file.");
success = false;
}

if (0 == commandLine.Sources.Count)
{
Console.Error.WriteLine("No source files specified. Specify at least one file.");
success = false;
}

return success;
}
}
75 changes: 75 additions & 0 deletions tools/SchemaValidator/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.

namespace WixBuildTools.SchemaValidator;

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;

public sealed class Program
{
public static int Main(string[] args)
{
if (!CommandLine.TryParseArguments(args, out var commandLine))
{
CommandLine.ShowHelp();
return 1;
}

Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Start run. Validating {commandLine.Sources.Count} source files against {commandLine.Schemas.Count} schemas.");

var settings = GetReaderSettings(commandLine);

var errors = 0;

foreach (var source in commandLine.Sources)
{
try
{
Validate(source, settings);
}
catch (XmlSchemaException xse)
{
++errors;
Console.WriteLine($"Encountered validation error in {source}({xse.LineNumber},{xse.LinePosition}): {xse.Message}");
}
}

Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Run complete. Encountered {errors} validation errors from {commandLine.Sources.Count} source files against {commandLine.Schemas.Count} schemas.");

return 0;
}

private static XmlReaderSettings GetReaderSettings(CommandLine commandLine)
{
var settings = new XmlReaderSettings
{
ValidationType = ValidationType.Schema,
ValidationFlags =
XmlSchemaValidationFlags.ReportValidationWarnings |
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation
};

foreach (var schema in commandLine.Schemas)
{
settings.Schemas.Add(null, schema);
}

return settings;
}

static void Validate(string xmlFile, XmlReaderSettings settings)
{
var document = new XmlDocument();
var reader = XmlReader.Create(xmlFile, settings);
document.Load(reader);
document.Validate(null);
}
}
10 changes: 10 additions & 0 deletions tools/SchemaValidator/SchemaValidator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>

0 comments on commit 32c33f0

Please sign in to comment.