Support #6300
closedHowto correctly validate a xml-file against a xslt file in Saxon version 10
0%
Description
I am new to Saxon, and have tried to validate a xml-file against a xslt file (based on the samples that comes with Saxon 10) - but I can't understand why a non valid xml-file gives no errors with the following code - even I have expected some errors reported:
String xmlFile = "C:\\InvoiceStor_v2p2.xml";
String styleFile = "C:\\OIOUBL_Invoice_Schematron.xsl";
Processor processor = new Processor();
DocumentBuilder builder = processor.NewDocumentBuilder();
builder.BaseUri = new Uri(xmlFile);
XdmNode input = builder.Build(File.OpenRead(xmlFile));
XsltCompiler compiler = processor.NewXsltCompiler();
compiler.BaseUri = new Uri(styleFile);
Xslt30Transformer transformer = compiler.Compile(File.OpenRead(styleFile)).Load30();
transformer.GlobalContextItem = input;
Serializer serializer = processor.NewSerializer();
serializer.SetOutputWriter(Console.Out);
transformer.ApplyTemplates(input, serializer);
try
{
compiler.Compile(new Uri(styleFile));
Console.WriteLine("Stylesheet compilation succeeded");
}
catch (Exception)
{
IList<XmlProcessingError> xmlProcessingErrors = compiler.GetErrorList();
Console.WriteLine("Stylesheet compilation failed with " + xmlProcessingErrors.Count + " errors");
for (int i = 0; i <= xmlProcessingErrors.Count - 1; i++)
{
Console.WriteLine("Stylesheet compilation failed with " + xmlProcessingErrors.Count + " errors");
}
}
I really hope that it is okay to ask this question in this forum. The main reason is that I am new to Saxon - and I want to validate a xml-file against a xslt-file. Maybe it is not the right way to do the coding - but honestly, I do not know how to do it :-(
Thanks in advance.
Regards Michael
Files
Updated by Michael Kay 11 months ago
Looks like you're trying to run a Schematron validation.
I'm no expert in Schematron, but I think (IIRC) the validation stylesheet is written to report validity errors in its normal output, rather than treating them as XSLT exceptions. That is, the XSLT should run successfully, and report any validation errors in its output file.
Updated by Michael Kay 11 months ago
One little point about your code, though: you're compiling the stylesheet twice (the second time within the try/catch) which is of course quite unnecessary.
You could also save a few lines of code by using the Xslt30Transformer.Transform()
method which means you don't need to build the source tree "by hand".
Updated by Michael Eriksen 11 months ago
Hello again
Thank you very much for commenting this - but I will be very glad if it is possible for someone to share a sample of howto make a xslt validating and then report the errors.
Thanks in advance, Michael
Updated by Martin Honnen 11 months ago
@Michael Eriksen,
basically, assuming the XSLT is already some Schematron transpiled to XSLT, you would usually run it against the XML input to get an XdmDestination, and then you need to look into that result, an SVRL report, for anything you consider a validation error, so assuming any failed assert in Schematron for you is a validation error, with XPath you could check for /Q{http://purl.oclc.org/dsdl/svrl}schematron-output!(Q{http://purl.oclc.org/dsdl/svrl}failed-assert
. If there are none, the Schematron validation passed, if there are any, these are the failed validations and you could output them.
Updated by Michael Kay 11 months ago
Can you perhaps attach the XML, XSLT, and the result of the transformation?
Updated by Michael Eriksen 11 months ago
- File MCE-Invoice.xml MCE-Invoice.xml added
- File OIOUBL_Invoice_Schematron.xsl OIOUBL_Invoice_Schematron.xsl added
I have now attached 2 files which I assume I have to use for xslt-validation. But I do not understand "the result of the transformation" - I can not see how to find this. But with the attached xml-file i know there should be 28 errors in according to xslt-validation. The purpose for me is to find them in a way with xslt-validation and to report these errors.
Regards Michael
Updated by Michael Kay 11 months ago
When I run the transformation from the command line like this:
java net.sf.saxon.Transform -xsl:OIOUBL_Invoice_schematron.xsl -s:MCE-Invoice.xml -t !indent=yes
I get output like this:
<?xml version="1.0" encoding="utf-8"?>
<Schematron xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:ccts="urn:oasis:names:specification:ubl:schema:xsd:CoreComponentParameters-2"
xmlns:doc="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:iso="http://purl.oclc.org/dsdl/schematron"
xmlns:sch="http://www.ascc.net/xml/schematron"
xmlns:sdt="urn:oasis:names:specification:ubl:schema:xsd:SpecializedDatatypes-2"
xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<Information>Checking OIOUBL-2.1 Invoice, 2023-02-06, Version 1.13.2.50919c6</Information>
<Error context="cac:OrderReference/cac:DocumentReference">
<Pattern>cac:Attachment/cbc:EmbeddedDocumentBinaryObject and cac:Attachment/cac:ExternalReference</Pattern>
<Description>[F-LIB171] Use either EmbeddedDocumentBinaryObject or ExternalReference</Description>
<Xpath>/Invoice[1]/cac:OrderReference[1]/cac:DocumentReference[1]</Xpath>
</Error>
<Error context="cac:BillingReference/cac:InvoiceDocumentReference">
<Pattern>cac:Attachment/cbc:EmbeddedDocumentBinaryObject and cac:Attachment/cac:ExternalReference</Pattern>
<Description>[F-LIB171] Use either EmbeddedDocumentBinaryObject or ExternalReference</Description>
<Xpath>/Invoice[1]/cac:BillingReference[1]/cac:InvoiceDocumentReference[1]</Xpath>
</Error>
....
The <Error>
elements in the output are your validation errors.
You can equally well run the transformation from your Java application using the s9api API if you prefer. The way you have written it, the transformation output is going to the Serializer
object, which is writing it to Console.Out
; but of course you can send it to a file if you prefer; or if you want to examine the validation report further in your Java application, you can send it to an XdmDestination
or DOMDestination
instead of to a Serializer
.
Updated by Michael Eriksen 11 months ago
Thank you very much for this - but how to do this with Saxon 10 to C#/.NET ? Is there a way for this output via c# ? Thanks in advance.
Regards Michael
Updated by Martin Honnen 11 months ago
@Michael Eriksen,
have you had a look at the C# samples on using Saxon 10 .NET in the resources download for Saxon 10 you can find at https://github.com/Saxonica/Saxon-HE/tree/main/10/resources?
They are also online, the complete file is https://saxonica.plan.io/projects/saxonmirrorhe/repository/he/revisions/he_mirror_saxon_10_9/entry/src/samples/cs/ExamplesHE.cs and has various examples on how to use XSLT, XPath and XQuery with Saxon 10 .NET, you might want to look into examples like https://saxonica.plan.io/projects/saxonmirrorhe/repository/he/revisions/he_mirror_saxon_10_9/entry/src/samples/cs/ExamplesHE.cs#L416 that run a transformation to the Console or like https://saxonica.plan.io/projects/saxonmirrorhe/repository/he/revisions/he_mirror_saxon_10_9/entry/src/samples/cs/ExamplesHE.cs#L721 that creates the result as an XdmDestination, on that you could then use XPath evaluation to count and/or output the Error
elements in the result.
Updated by Martin Honnen 11 months ago
Simple command line app accepting the XSLT and the XML file names as the command line arguments would be alike
using System;
using System.IO;
using Saxon.Api;
namespace SaxonHE10NetOIOUBLInvoiceValidation
{
internal class Program
{
static void Main(string[] args)
{
Processor processor = new Processor();
XsltCompiler xsltCompiler = processor.NewXsltCompiler();
XsltExecutable xsltExecutable = xsltCompiler.Compile(new Uri(Path.Combine(Environment.CurrentDirectory, args[0])));
Xslt30Transformer xslt30Transformer = xsltExecutable.Load30();
XdmDestination validationReport = new XdmDestination();
using (var inputStream = File.OpenRead(args[1]))
{
xslt30Transformer.Transform(inputStream, new Uri(Path.Combine(Environment.CurrentDirectory, args[1])), validationReport);
}
XPathCompiler xpathCompiler = processor.NewXPathCompiler();
var validationErrors = xpathCompiler.Evaluate("//Error", validationReport.XdmNode);
if (validationErrors.Count > 0)
{
Console.WriteLine("Validation failed with " + validationErrors.Count + " error(s):");
Console.WriteLine(validationErrors);
}
else
{
Console.WriteLine("Input file " + args[1] + " is valid against compiled Schematron " + args[0] + ".");
}
}
}
}
Updated by Michael Eriksen 11 months ago
Thank you very much.
I have already taken a deep look into your samples and tried to make the abovementioned code based on these samples to Version 10 - but honestly I don't think I can understand what I need to do :-( So therefore I have tried to ask here in this forum - I really hope that it is okay...
So what I need do do in C#/.NET for reporting XLST errors in a XML-file - unfortunately I can't figure out :-(
Regards Michael
Updated by Michael Eriksen 11 months ago
@Martin Honnen
Thank you very much for this sample - I will take a deep look into it.
Thanks again :-)
Regards Michael
Updated by Michael Eriksen 11 months ago
Thank you very much for this codesample - I have now got it to work exactly as I wish :-) So Thanks again... Regards Michael
Updated by Michael Kay 9 months ago
- Status changed from New to Closed
Closing because the conversation seems to have ended.
Please register to edit this issue