/// /// 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; }