///
/// Applies an xsl transform to a source xml. Accommodates xsl transforms that produce one or more output files.
///
/// The root xsl transform file.
/// The xml source to transform.
/// The xml source file name.
/// List of transformed output. Key is the file name, Value is the file contents.
/// Xslt compile error messages
/// True if no errors were encountered.
public static bool BasicXslTransform(string xsltRoot, string source, string sourceFileName, out List> transformed, out string errorMessage)
{
transformed = null;
errorMessage = string.Empty;
try
{
//=====
// Create a Saxon Processor instance.
//=====
Processor processor = new Processor();
var builder = processor.NewDocumentBuilder();
// Set the basic settings for the builder
builder.BaseUri = new Uri("file:///");
builder.DtdValidation = false;
// Create a process task resolver to ensure that the DTD handling is
// managed properly.
ProcessTaskXmlResolver customResolver = new ProcessTaskXmlResolver();
builder.XmlResolver = customResolver;
// Load the source document
var input = string.IsNullOrWhiteSpace(source) ? builder.Build(new Uri(sourceFileName)) : builder.Build(source.ToStream());
// Create a compiler
XsltCompiler compiler = processor.NewXsltCompiler();
Xslt30Transformer transformerRoot = compiler.Compile(xsltRoot.ToStream()).Load30();
XdmDestination rootResults = new XdmDestination();
transformerRoot.GlobalContextItem = input;
//=====
// Set the ResultDocumentHandler
//
// This is used to process any result documents generated by the transform via the document-result
// XSLT processing instruction.
//=====
Hashtable xmlDocumentResultsHT = new Hashtable();
transformerRoot.ResultDocumentHandler = new XmlProcessResultDocumentHandlerSaxon(xmlDocumentResultsHT);
// Use the default base of "file:///" for generating any output files.
transformerRoot.BaseOutputURI = "file:///";
var tester = transformerRoot.InputXmlResolver;
// Apply the root transform to the document
transformerRoot.ApplyTemplates(input, rootResults);
//=====
// Determine the output file list
//=====
transformed = new List>();
// Add the main output file (typical case) where there is
// a single transformed output file.
if (!string.IsNullOrWhiteSpace(rootResults.XdmNode?.OuterXml))
{
var XmlOutput = rootResults.XdmNode.OuterXml;
var kvp = new KeyValuePair(sourceFileName, XmlOutput);
transformed.Add(kvp);
}
// Next add any output files generated from the document-result transform instruction
foreach (var fileNameResultsKey in xmlDocumentResultsHT.Keys)
{
//Previously:
//var theXmlOutput = ((DomDestination)xmlDocumentResultsHT[fileNameResultsKey])?.XmlDocument?.OuterXml ?? string.Empty;
// CORRECTED:
var XmlOutput = ((XdmDestination)xmlDocumentResultsHT[fileNameResultsKey])?.XdmNode?.OuterXml;
var kvp2 = new KeyValuePair(fileNameResultsKey.ToString(), XmlOutput);
transformed.Add(kvp2);
}
}
catch (Exception ex)
{
errorMessage = ex.Message;
return false;
}
return true;
}
///
/// Event Handler for result file creation. This method gets called once
/// for each document-result operation in the XSLT transform.
///
/// The filename being generated.
/// The base URI to use for the filename.
/// An XmlDestination object to store the result document content within.
public XmlDestination HandleResultDocument(string href, Uri baseUri)
{
//DomDestination destination = new DomDestination();
//ResultDocumentHashtable[href] = destination;
//return destination;
// CORRECTED: to use XdmDestination
XdmDestination dest = new XdmDestination();
ResultDocumentHashtable[href] = dest;
return dest;
}