This post is a continuation to the Schematron validation using XSLT in BizTalk blog series
The source code for this blog post has been uploaded in the below location
Now that you know about the basic schematron XSLT implementation, we will now see how we can achieve this in BizTalk.
High Level steps for BizTalk implementation
1. Create the schematron-output schema which we discussed in the last section
2. Create a custom pipeline component( Any Category type, so that we can have the component in any of the pipeline stage, except disassembling stage)
a. Implement Custom UI functionality so that we can have the Schematron rules as property. We are also going to add a property to hold the physical path to the conformance1-5.xsl. So it is important that the conformance1-5.xsl and the skeleton1-5.xsl is placed in appropriate directories.
b. If we have any schematron errors, then we will promote the message type with the schematron output message type.
3. Apply an inbound map in the receive port if transformation is required(Optional Step)
Detailed Steps for BizTalk implementation
1. I will skip the creation of schematron-output schema .
2. Custom Pipeline component
The pipeline component has three parts
a. The component itself
b. Custom UI form
c. Custom UI Type Editor class
The custom UI is a windows form which can accept the XSLT and store it in a XML serialized format. This is pretty useful, as we can load the XSLT stylesheet from the pipeline component property itself.
The code for Custom UI and Type Editor Class are self-explanatory and I will proceed with the actual transformation logic.
public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inMsg)
ReadOnlySeekableStream seekableStm = new ReadOnlySeekableStream(inMsg.BodyPart.Data);
VirtualStream vs = null;
XmlTextReader stylesheet = new XmlTextReader(new StringReader(this.SchematronXSLT));
XmlTextReader conformanceStylesheet = new XmlTextReader(this.ConformanceXSLTPath);
// Load transform
BTSXslTransform trans = new BTSXslTransform();
XmlTextReader inputReader = new XmlTextReader(seekableStm);
//Create memory stream to hold transformed data.
vs = new VirtualStream(VirtualStream.MemoryFlag.AutoOverFlowToDisk);
trans.ScalableTransform(stylesheet, null, vs, new XmlUrlResolver(), false);
XmlTextReader validatingXSLReader = new XmlTextReader(vs);
BTSXslTransform ValidatingTrans = new BTSXslTransform();
VirtualStream vs1 = new VirtualStream(VirtualStream.MemoryFlag.AutoOverFlowToDisk);
ValidatingTrans.ScalableTransform(inputReader, null, vs1, new XmlUrlResolver(), false);
XmlDocument outputDoc = new XmlDocument();
if (outputDoc.SelectNodes(“//failed-assert”).Count > 0)
inMsg.BodyPart.Data = vs1;
inMsg.Context.Promote(“MessageType”, “http://schemas.microsoft.com/BizTalk/2003/system-properties”, “http://www.ascc.net/xml/schematron#schematron-output”);
inMsg.BodyPart.Data.Position = 0;
inMsg.BodyPart.Data = seekableStm;
catch (Exception ex)
Key things from the above code is I have used BTSXslTransform class to do the transformation and used VirtualStream to hold the transformed data. One nice feature about VirtualStream is that it is initialized with VirtualStream.MemoryFlag.AutoOverFlowToDisk i.e. when the internal memory is not sufficient to hold the transformed data, it will be stored to the disk. This is greatly useful in case of large messages.
Other than that, the code is quite simple to follow.
So far, we have seen the development of the schematron XSLT infrastructure and how to use it with BizTalk. This part of the tutorial is only a beginner and we will see more complex schematron in the upcoming posts.