Schematron and embed C#
How to include embed C# in the XML validation protocol, Schematron.
Some of you may remember the blog post about Schematron and BizTalk. At the same customer we ran into a problem where we needed to validate a date time against the system date time. Since xslt 2.0 there is a build-in function available, unfortunately in xslt 1.0 we needed to create a workaround.
We looked at multiple solutions; convert the date time to its number value, split the date time and compare the days, months, etc. All of them would be to complex, so we looked at a way to include embed C# since we use the .NET xslt compiler.
A small recap, the Schematron file needs to correspond with the schematron1-5.xsd, in order to use skeleton1-5.xsl to create the xslt used by the xslt compiler.
We came up with the following strategy:
- Include usescripts tag at the start of the schematron file to indicate the use of C# code
- Include scripts/script (unbound) at the end of the schematron file to indicate which C# code that are used
- Use embed C# code (1)
- The C# code is stored in a separate xsl file
We started by adapting the Schematron1-5.xsd:
Next we created a new xsl, customscripts.xsl, which contains the scripts. The file is imported in the skeleton1-5.xsl file.
In order to identify which C# code, the value of scripts/script needs to correspond with the value in the if statement.
One other thing to keep in mind, Xpath passes parameters as a string. This means that we need to convert the parameters into the corresponding C# object. In our case the values that we need to compare are thoroughly defined in the xsd of the messages. That’s the reason why we didn’t use TryParse. If you not a 100% sure about the correctness of the values, we recommend that you use TryParse.
The only thing remaining is to adapt the skeleton1-5.xsl file.
First we need to import the customscripts.xsl file. It’s done by using the xsl:import statement.
In order to include the namespace and prefix, we added a test to see if usescripts is present.
The final change is the call the template from customscripts.xsl to create the msxsl:script record.
The two changes above are within <xsl:template match=”sch:schema | schema”> because we use schema as root element for the Schematron file. If you have chosen another approach that corresponds with the standard, you need to include the changes under the corresponding template.
We adapted the previous blog post example to make it clearer. The element DateOfBirth is added to the import xml and the value needs to be in the past.
The Schematron file is extended with
<sch:usescripts /> and
<sch:script>DateLessThan</sch:script> <sch:script>GetCurrentDate</sch:script> </sch:scripts>
After creating the xslt, we get the following result:
As you can see msxsl:script is added at the end, with the methods DateLessThan and GetCurrentDate as embed code.
- This will only work when you use a .NET xslt compiler
- The name of the script must correspond with the value used in the if statement
- Easiest way to import the customscripts.xsl is to place it in the same directory as the skeleton1-5.xsl
- Don’t forget to convert the values if needed
- If the code preforms a test, make sure it return only true of false
Since we to the validation within BizTalk, using embed C# code is the most obvious choice for this project. There definitely are other ways of solving this problem, like an extension object. It all depends on the project’s needs.