Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,5 @@ dotnet test Schematron.slnx

## Conventions

- **Target framework**: `net48` for all projects (WebServices requires .NET Framework due to `System.Web.Services`).
- **Versioning**: Managed by the [GitInfo](https://github.com/devlooped/GitInfo) package; base version comes from the `VERSION` file at the repo root.
- **NuGet metadata**: Defined in `src/Directory.Build.props` and per-project `<PropertyGroup>`.
- **C# language version**: `latest` — use modern idioms (expression-bodied members, `var`, `string.IsNullOrEmpty`, `throw;`, pattern matching).
- **No custom build scripts**: Use standard `dotnet` CLI; no `build.cmd` / `build.proj`.
12 changes: 6 additions & 6 deletions src/Schematron.Tests/ReferenceSchematronRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ static class ReferenceSchematronRunner
const string XsltDir = "./Content/xslt";
const string SvrlNs = "http://purl.oclc.org/dsdl/svrl";

static readonly XslCompiledTransform _include = LoadXslt(Path.Combine(XsltDir, "iso_dsdl_include.xsl"));
static readonly XslCompiledTransform _abstract = LoadXslt(Path.Combine(XsltDir, "iso_abstract_expand.xsl"));
static readonly XslCompiledTransform _svrl = LoadXslt(Path.Combine(XsltDir, "iso_svrl_for_xslt1.xsl"));
static readonly XslCompiledTransform include = LoadXslt(Path.Combine(XsltDir, "iso_dsdl_include.xsl"));
static readonly XslCompiledTransform abstractExpand = LoadXslt(Path.Combine(XsltDir, "iso_abstract_expand.xsl"));
static readonly XslCompiledTransform svrl = LoadXslt(Path.Combine(XsltDir, "iso_svrl_for_xslt1.xsl"));

static XslCompiledTransform LoadXslt(string path)
{
Expand All @@ -36,14 +36,14 @@ static XslCompiledTransform LoadXslt(string path)
public static SvrlResult Validate(string schemaPath, string xmlContent, string? phase = null)
{
// Step 1: resolve includes
string included = ApplyTransform(_include, ReadFile(schemaPath), baseUri: Path.GetFullPath(schemaPath));
string included = ApplyTransform(include, ReadFile(schemaPath), baseUri: Path.GetFullPath(schemaPath));
// Step 2: expand abstract patterns
string expanded = ApplyTransform(_abstract, included);
string expanded = ApplyTransform(abstractExpand, included);
// Step 3: generate validator XSLT from schema
var svrlArgs = new XsltArgumentList();
if (!string.IsNullOrEmpty(phase))
svrlArgs.AddParam("phase", "", phase);
string validatorXslt = ApplyTransform(_svrl, expanded, args: svrlArgs);
string validatorXslt = ApplyTransform(ReferenceSchematronRunner.svrl, expanded, args: svrlArgs);
// Step 4: apply validator XSLT to the XML instance
var validator = new XslCompiledTransform();
using (var validatorReader = XmlReader.Create(new StringReader(validatorXslt)))
Expand Down
17 changes: 4 additions & 13 deletions src/Schematron.Tests/Schematron.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,15 @@
</PropertyGroup>

<ItemGroup>
<Content Include="Content\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\xslt\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\compat\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\*" CopyToOutputDirectory="PreserveNewest" />
<Content Include="Content\xslt\*" CopyToOutputDirectory="PreserveNewest" />
<Content Include="Content\compat\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="xunit" Version="2.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
</ItemGroup>

<ItemGroup>
Expand Down
7 changes: 3 additions & 4 deletions src/Schematron.Tests/ValidatorTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
Expand Down Expand Up @@ -78,7 +77,7 @@ public void ValidateShouldReturnSchematronValidationResultWhenSchematronConstrai
using (var stream = new MemoryStream(System.Text.Encoding.Unicode.GetBytes(ex.Message)))
using (var reader = XmlReader.Create(stream))
{
var obj = (Schematron.Serialization.SchematronValidationResultTempObjectModel.Output)serializer.Deserialize(reader);
var obj = (Schematron.Serialization.SchematronValidationResultTempObjectModel.Output?)serializer.Deserialize(reader);

// Assert

Expand Down Expand Up @@ -282,7 +281,7 @@ public void SchematronValidationResultIncludesExpandedValueElements()

using (var doc = XmlReader.Create(XmlContentLocation))
{
var result = (IXPathNavigable)null;
IXPathNavigable? result = default;

try
{
Expand All @@ -292,7 +291,7 @@ public void SchematronValidationResultIncludesExpandedValueElements()
{
System.Diagnostics.Debug.WriteLine(ex.Message);
string expectedMessage = "<text>Attributes sex (Female) and title (Mr) must have compatible values on element customer.</text>";
Xunit.Assert.True(ex.Message.Contains(expectedMessage));
Xunit.Assert.Contains(expectedMessage, ex.Message);
}
Xunit.Assert.Null(result);
}
Expand Down
4 changes: 1 addition & 3 deletions src/Schematron/Assert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ public class Assert : Test
/// <summary>Constructs a new Assert object.</summary>
/// <param name="test">XPath expression to test.</param>
/// <param name="message">Message to display if the assert fails.</param>
internal protected Assert(string test, string message) : base(test, message)
{
}
internal protected Assert(string test, string message) : base(test, message) { }
}

18 changes: 4 additions & 14 deletions src/Schematron/BadSchemaException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,26 @@ public class BadSchemaException : ApplicationException
/// <summary>
/// Initializes a new instance of the <see cref="BadSchemaException"/> class.
/// </summary>
public BadSchemaException()
{
}
public BadSchemaException() { }

/// <summary>
/// Initializes a new instance of the <see cref="BadSchemaException"/> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public BadSchemaException(string message) : base(message)
{
}
public BadSchemaException(string message) : base(message) { }

/// <summary>
/// Initializes a new instance of the <see cref="BadSchemaException"/> class.
/// </summary>
/// <param name="info">Info</param>
/// <param name="context">Context</param>
protected BadSchemaException(SerializationInfo info, StreamingContext context) :
base(info, context)
{
}
protected BadSchemaException(SerializationInfo info, StreamingContext context) : base(info, context) { }

/// <summary>
/// Initializes a new instance of the <see cref="BadSchemaException"/> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception.</param>
public BadSchemaException(string message, Exception innerException) :
base(message, innerException)
{
}
public BadSchemaException(string message, Exception innerException) : base(message, innerException) { }
}

7 changes: 2 additions & 5 deletions src/Schematron/CompiledExpressions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Xml;
using System.Xml.XPath;

namespace Schematron;
Expand Down Expand Up @@ -32,7 +31,7 @@ class CompiledExpressions

static CompiledExpressions()
{
XmlNamespaceManager mgr = Config.DefaultNsManager;
var mgr = Config.DefaultNsManager;

Schema = Config.DefaultNavigator.Compile("//sch:schema");
Schema.SetContext(mgr);
Expand Down Expand Up @@ -75,8 +74,6 @@ static CompiledExpressions()
// Diagnostics.SetContext(mgr);
}

CompiledExpressions()
{
}
CompiledExpressions() { }
}

162 changes: 68 additions & 94 deletions src/Schematron/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,87 +11,83 @@ namespace Schematron;
/// This class is public to allow inheritors of Schematron elements
/// to use these global settings.
/// </remarks>
/// <author ref="kzu" />
/// <progress amount="100" />
public class Config
{
static readonly IFormatter formatter;
static readonly XPathNavigator navigator;
static readonly XmlNamespaceManager nsmanager;
static readonly Schema full;
static readonly Schema embedded;
static readonly string uid = string.Intern(Guid.NewGuid().ToString());

/// <summary>
/// Initializes global settings.
/// </summary>
static Config()
{
// Default formatter outputs in text format a log with results.
_formatter = new LogFormatter();
formatter = new LogFormatter();

//TODO: create and load the schematron full and embedded versions for validation.
_embedded = new Schema();
_embedded.Phases.Add(_embedded.CreatePhase(Phase.All));
_full = new Schema();
_full.Phases.Add(_full.CreatePhase(Phase.All));
embedded = new Schema();
embedded.Phases.Add(embedded.CreatePhase(Phase.All));
full = new Schema();
full.Phases.Add(full.CreatePhase(Phase.All));

//TODO: should we move all the schema language elements to a resource file?
_navigator = new XmlDocument().CreateNavigator();
_navigator.NameTable.Add("active");
_navigator.NameTable.Add("pattern");
_navigator.NameTable.Add("assert");
_navigator.NameTable.Add("test");
_navigator.NameTable.Add("role");
_navigator.NameTable.Add("id");
_navigator.NameTable.Add("diagnostics");
_navigator.NameTable.Add("icon");
_navigator.NameTable.Add("subject");
_navigator.NameTable.Add("diagnostic");
_navigator.NameTable.Add("dir");
_navigator.NameTable.Add("emph");
_navigator.NameTable.Add("extends");
_navigator.NameTable.Add("rule");
_navigator.NameTable.Add("key");
_navigator.NameTable.Add("name");
_navigator.NameTable.Add("path");
_navigator.NameTable.Add("ns");
_navigator.NameTable.Add("uri");
_navigator.NameTable.Add("prefix");
_navigator.NameTable.Add("p");
_navigator.NameTable.Add("class");
_navigator.NameTable.Add("see");
_navigator.NameTable.Add("phase");
_navigator.NameTable.Add("fpi");
_navigator.NameTable.Add("report");
_navigator.NameTable.Add("context");
_navigator.NameTable.Add("abstract");
_navigator.NameTable.Add("schema");
_navigator.NameTable.Add("schemaVersion");
_navigator.NameTable.Add("defaultPhase");
_navigator.NameTable.Add("version");
_navigator.NameTable.Add("span");
_navigator.NameTable.Add("title");
_navigator.NameTable.Add("value-of");
_navigator.NameTable.Add("select");
_navigator.NameTable.Add(Schema.IsoNamespace);
_navigator.NameTable.Add(Schema.LegacyNamespace);
navigator = new XmlDocument().CreateNavigator();
navigator.NameTable.Add("active");
navigator.NameTable.Add("pattern");
navigator.NameTable.Add("assert");
navigator.NameTable.Add("test");
navigator.NameTable.Add("role");
navigator.NameTable.Add("id");
navigator.NameTable.Add("diagnostics");
navigator.NameTable.Add("icon");
navigator.NameTable.Add("subject");
navigator.NameTable.Add("diagnostic");
navigator.NameTable.Add("dir");
navigator.NameTable.Add("emph");
navigator.NameTable.Add("extends");
navigator.NameTable.Add("rule");
navigator.NameTable.Add("key");
navigator.NameTable.Add("name");
navigator.NameTable.Add("path");
navigator.NameTable.Add("ns");
navigator.NameTable.Add("uri");
navigator.NameTable.Add("prefix");
navigator.NameTable.Add("p");
navigator.NameTable.Add("class");
navigator.NameTable.Add("see");
navigator.NameTable.Add("phase");
navigator.NameTable.Add("fpi");
navigator.NameTable.Add("report");
navigator.NameTable.Add("context");
navigator.NameTable.Add("abstract");
navigator.NameTable.Add("schema");
navigator.NameTable.Add("schemaVersion");
navigator.NameTable.Add("defaultPhase");
navigator.NameTable.Add("version");
navigator.NameTable.Add("span");
navigator.NameTable.Add("title");
navigator.NameTable.Add("value-of");
navigator.NameTable.Add("select");
navigator.NameTable.Add(Schema.IsoNamespace);
navigator.NameTable.Add(Schema.LegacyNamespace);

//Namespace manager initialization
_nsmanager = new XmlNamespaceManager(_navigator.NameTable);
_nsmanager.AddNamespace(String.Empty, Schema.Namespace);
_nsmanager.AddNamespace("sch", Schema.Namespace);
_nsmanager.AddNamespace("xsd", System.Xml.Schema.XmlSchema.Namespace);
}

Config()
{
nsmanager = new XmlNamespaceManager(navigator.NameTable);
nsmanager.AddNamespace(string.Empty, Schema.Namespace);
nsmanager.AddNamespace("sch", Schema.Namespace);
nsmanager.AddNamespace("xsd", System.Xml.Schema.XmlSchema.Namespace);
}

static IFormatter _formatter;
Config() { }

/// <summary>
/// The default object to use to format messages from validation.
/// </summary>
public static IFormatter DefaultFormatter
{
get { return _formatter; }
}

static XPathNavigator _navigator;
public static IFormatter DefaultFormatter => formatter;

/// <summary>
/// A default empty navigator used to pre-compile XPath expressions.
Expand All @@ -110,56 +106,35 @@ public static IFormatter DefaultFormatter
/// <seealso cref="CompiledExpressions"/>
/// </para>
/// </example>
internal static XPathNavigator DefaultNavigator
{
// Returning a cloned navigator appeared to solve the threading issues
// we had, because a single navigator was being used to compile all the
// expressions in all potential threads.
get { return _navigator.Clone(); }
}

static XmlNamespaceManager _nsmanager;
/// <devdoc>
/// Returning a cloned navigator appeared to solve the threading issues
/// we had, because a single navigator was being used to compile all the
/// expressions in all potential threads.
/// </devdoc>
internal static XPathNavigator DefaultNavigator => navigator.Clone();

/// <summary>
/// Manager to use when executing expressions that validate or
/// load Schematron and Embedded Schematron schemas.
/// </summary>
public static XmlNamespaceManager DefaultNsManager
{
get { return _nsmanager; }
}

static Schema _full;
public static XmlNamespaceManager DefaultNsManager => nsmanager;

/// <summary>
/// A cached schema in Schematron format to validate schematron schemas.
/// </summary>
/// <remarks>This is the version for standalone schemas.</remarks>
public static Schema FullSchematron
{
get { return _full; }
}

static Schema _embedded;
public static Schema FullSchematron => full;

/// <summary>
/// A cached schema in Schematron format to validate schematron schemas.
/// </summary>
/// <remarks>This is the version for embedded schemas.</remarks>
public static Schema EmbeddedSchematron
{
get { return _embedded; }
}

static string _uid = String.Intern(Guid.NewGuid().ToString());
public static Schema EmbeddedSchematron => embedded;

/// <summary>
/// A unique identifier to use for internal keys.
/// </summary>
public static string UniqueKey
{
get { return _uid; }
}
public static string UniqueKey => uid;

/// <summary>
/// Force all static constructors in the library.
Expand All @@ -171,5 +146,4 @@ public static void Setup()
System.Diagnostics.Trace.Write(TagExpressions.Dir.RightToLeft);
System.Diagnostics.Trace.WriteLine(FormattingUtils.XmlErrorPosition.RightToLeft);
}
}

}
Loading
Loading