The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl \ XslCompiledTransform

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XslCompiledTransform.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. // <spec>http://webdata/xml/specs/XslCompiledTransform.xml</spec>
  15. //------------------------------------------------------------------------------
  16. using System.CodeDom.Compiler;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using System.IO;
  20. using System.Xml.XPath;
  21. using System.Xml.Xsl.Qil;
  22. using System.Xml.Xsl.Runtime;
  23. using System.Xml.Xsl.XPath;
  24. using System.Xml.Xsl.Xslt;
  25. using System.Security.Permissions;
  26. namespace System.Xml.Xsl
  27. {
  28.     #if ! HIDE_XSL
  29.     using XsltCompiler = System.Xml.Xsl.Xslt.Compiler;
  30.    
  31.     //----------------------------------------------------------------------------------------------------
  32.     // Clarification on null values in this API:
  33.     // stylesheet, stylesheetUri - cannot be null
  34.     // settings - if null, XsltSettings.Default will be used
  35.     // stylesheetResolver - if null, XmlNullResolver will be used for includes/imports.
  36.     // However, if the principal stylesheet is given by its URI, that
  37.     // URI will be resolved using XmlUrlResolver (for compatibility
  38.     // with XslTransform and XmlReader).
  39.     // documentResolver - if null, XmlNullResolver will be used
  40.     // input, inputUri - cannot be null
  41.     // arguments - null means no arguments
  42.     // results, resultsFile - cannot be null
  43.     //----------------------------------------------------------------------------------------------------
  44.    
  45.     public sealed class XslCompiledTransform
  46.     {
  47.         // Options of compilation
  48.         private bool enableDebug = false;
  49.        
  50.         // Results of compilation
  51.         private CompilerResults compilerResults = null;
  52.         private XmlWriterSettings outputSettings = null;
  53.         private QilExpression qil = null;
  54.         private XmlCommand command = null;
  55.        
  56.         public XslCompiledTransform()
  57.         {
  58.         }
  59.        
  60.         public XslCompiledTransform(bool enableDebug)
  61.         {
  62.             this.enableDebug = enableDebug;
  63.         }
  64.        
  65.         /// <summary>
  66.         /// This function is called on every recompilation to discard all previous results
  67.         /// </summary>
  68.         private void Reset()
  69.         {
  70.             compilerResults = null;
  71.             outputSettings = null;
  72.             qil = null;
  73.             command = null;
  74.         }
  75.        
  76.         internal CompilerErrorCollection Errors {
  77.             get { return compilerResults != null ? compilerResults.Errors : null; }
  78.         }
  79.        
  80.         /// <summary>
  81.         /// Writer settings specified in the stylesheet
  82.         /// </summary>
  83.         public XmlWriterSettings OutputSettings {
  84.             get { return outputSettings; }
  85.         }
  86.        
  87.         public TempFileCollection TemporaryFiles {
  88.             [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
  89.             get { return compilerResults != null ? compilerResults.TempFiles : null; }
  90.         }
  91.        
  92.         //------------------------------------------------
  93.         // Load methods
  94.         //------------------------------------------------
  95.        
  96.         public void Load(XmlReader stylesheet)
  97.         {
  98.             Reset();
  99.             LoadInternal(stylesheet, XsltSettings.Default, new XmlUrlResolver());
  100.         }
  101.        
  102.         public void Load(XmlReader stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
  103.         {
  104.             Reset();
  105.             LoadInternal(stylesheet, settings, stylesheetResolver);
  106.         }
  107.        
  108.         public void Load(IXPathNavigable stylesheet)
  109.         {
  110.             Reset();
  111.             LoadInternal(stylesheet, XsltSettings.Default, new XmlUrlResolver());
  112.         }
  113.        
  114.         public void Load(IXPathNavigable stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
  115.         {
  116.             Reset();
  117.             LoadInternal(stylesheet, settings, stylesheetResolver);
  118.         }
  119.        
  120.         public void Load(string stylesheetUri)
  121.         {
  122.             Reset();
  123.             if (stylesheetUri == null) {
  124.                 throw new ArgumentNullException("stylesheetUri");
  125.             }
  126.             LoadInternal(stylesheetUri, XsltSettings.Default, new XmlUrlResolver());
  127.         }
  128.        
  129.         public void Load(string stylesheetUri, XsltSettings settings, XmlResolver stylesheetResolver)
  130.         {
  131.             Reset();
  132.             if (stylesheetUri == null) {
  133.                 throw new ArgumentNullException("stylesheetUri");
  134.             }
  135.             LoadInternal(stylesheetUri, settings, stylesheetResolver);
  136.         }
  137.        
  138.         private CompilerResults LoadInternal(object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
  139.         {
  140.             if (stylesheet == null) {
  141.                 throw new ArgumentNullException("stylesheet");
  142.             }
  143.             if (settings == null) {
  144.                 settings = XsltSettings.Default;
  145.             }
  146.             CompileToQil(stylesheet, settings, stylesheetResolver);
  147.             CompilerError error = FirstError();
  148.             if (error != null) {
  149.                 throw new XslLoadException(error);
  150.             }
  151.             if (!settings.CheckOnly) {
  152.                 CompileIlFromQil(settings);
  153.             }
  154.             return compilerResults;
  155.         }
  156.        
  157.         private void CompileToQil(object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
  158.         {
  159.             settings.IncludeDebugInformation |= enableDebug;
  160.             XsltCompiler compiler = new XsltCompiler(settings);
  161.             compilerResults = compiler.Compile(stylesheet, stylesheetResolver, out qil);
  162.         }
  163.        
  164.         /// <summary>
  165.         /// Returns the first compiler error except warnings
  166.         /// </summary>
  167.         private CompilerError FirstError()
  168.         {
  169.             foreach (CompilerError error in compilerResults.Errors) {
  170.                 if (!error.IsWarning) {
  171.                     return error;
  172.                 }
  173.             }
  174.             return null;
  175.         }
  176.        
  177.         private void CompileIlFromQil(XsltSettings settings)
  178.         {
  179.             command = new XmlILGenerator().Generate(qil, settings.AssemblyName);
  180.             // Set outputSettings only if compilation was successful
  181.             outputSettings = qil.DefaultWriterSettings;
  182.             qil = null;
  183.         }
  184.        
  185.         //------------------------------------------------
  186.         // Transform methods which take an IXPathNavigable
  187.         //------------------------------------------------
  188.        
  189.         public void Transform(IXPathNavigable input, XmlWriter results)
  190.         {
  191.             CheckCommand();
  192.             CheckInput(input);
  193.             command.Execute(input, new XmlUrlResolver(), (XsltArgumentList)null, results);
  194.         }
  195.        
  196.         public void Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results)
  197.         {
  198.             CheckCommand();
  199.             CheckInput(input);
  200.             command.Execute(input, new XmlUrlResolver(), arguments, results);
  201.         }
  202.        
  203.         public void Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results)
  204.         {
  205.             CheckCommand();
  206.             CheckInput(input);
  207.             command.Execute(input, new XmlUrlResolver(), arguments, results);
  208.         }
  209.        
  210.         public void Transform(IXPathNavigable input, XsltArgumentList arguments, Stream results)
  211.         {
  212.             CheckCommand();
  213.             CheckInput(input);
  214.             command.Execute(input, new XmlUrlResolver(), arguments, results);
  215.         }
  216.        
  217.         //------------------------------------------------
  218.         // Transform methods which take an XmlReader
  219.         //------------------------------------------------
  220.        
  221.         public void Transform(XmlReader input, XmlWriter results)
  222.         {
  223.             CheckCommand();
  224.             CheckInput(input);
  225.             command.Execute(input, new XmlUrlResolver(), (XsltArgumentList)null, results);
  226.         }
  227.        
  228.         public void Transform(XmlReader input, XsltArgumentList arguments, XmlWriter results)
  229.         {
  230.             CheckCommand();
  231.             CheckInput(input);
  232.             command.Execute(input, new XmlUrlResolver(), arguments, results);
  233.         }
  234.        
  235.         public void Transform(XmlReader input, XsltArgumentList arguments, TextWriter results)
  236.         {
  237.             CheckCommand();
  238.             CheckInput(input);
  239.             command.Execute(input, new XmlUrlResolver(), arguments, results);
  240.         }
  241.        
  242.         public void Transform(XmlReader input, XsltArgumentList arguments, Stream results)
  243.         {
  244.             CheckCommand();
  245.             CheckInput(input);
  246.             command.Execute(input, new XmlUrlResolver(), arguments, results);
  247.         }
  248.        
  249.         public void Transform(XmlReader input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver)
  250.         {
  251.             CheckCommand();
  252.             CheckInput(input);
  253.             command.Execute(input, documentResolver, arguments, results);
  254.         }
  255.        
  256.         //------------------------------------------------
  257.         // Transform methods which take a uri
  258.         //------------------------------------------------
  259.        
  260.         public void Transform(string inputUri, string resultsFile)
  261.         {
  262.             CheckCommand();
  263.             // SQLBUDT 276415: Prevent wiping out the content of the input file if the output file is the same
  264.             using (XmlReader input = CreateReader(inputUri)) {
  265.                 if (resultsFile == null) {
  266.                     throw new ArgumentNullException("resultsFile");
  267.                 }
  268.                 using (FileStream output = new FileStream(resultsFile, FileMode.Create, FileAccess.Write)) {
  269.                     command.Execute(input, new XmlUrlResolver(), (XsltArgumentList)null, output);
  270.                 }
  271.             }
  272.         }
  273.        
  274.         public void Transform(string inputUri, XmlWriter results)
  275.         {
  276.             CheckCommand();
  277.             using (XmlReader input = CreateReader(inputUri)) {
  278.                 command.Execute(input, new XmlUrlResolver(), (XsltArgumentList)null, results);
  279.             }
  280.         }
  281.        
  282.         public void Transform(string inputUri, XsltArgumentList arguments, XmlWriter results)
  283.         {
  284.             CheckCommand();
  285.             using (XmlReader input = CreateReader(inputUri)) {
  286.                 command.Execute(input, new XmlUrlResolver(), arguments, results);
  287.             }
  288.         }
  289.        
  290.         public void Transform(string inputUri, XsltArgumentList arguments, TextWriter results)
  291.         {
  292.             CheckCommand();
  293.             using (XmlReader input = CreateReader(inputUri)) {
  294.                 command.Execute(input, new XmlUrlResolver(), arguments, results);
  295.             }
  296.         }
  297.        
  298.         public void Transform(string inputUri, XsltArgumentList arguments, Stream results)
  299.         {
  300.             CheckCommand();
  301.             using (XmlReader input = CreateReader(inputUri)) {
  302.                 command.Execute(input, new XmlUrlResolver(), arguments, results);
  303.             }
  304.         }
  305.        
  306.         //------------------------------------------------
  307.         // Helper methods
  308.         //------------------------------------------------
  309.        
  310.         private void CheckCommand()
  311.         {
  312.             if (command == null) {
  313.                 throw new InvalidOperationException(Res.GetString(Res.Xslt_NoStylesheetLoaded));
  314.             }
  315.         }
  316.        
  317.         private void CheckInput(object input)
  318.         {
  319.             if (input == null) {
  320.                 throw new System.ArgumentNullException("input");
  321.             }
  322.         }
  323.        
  324.         private XmlReader CreateReader(string inputUri)
  325.         {
  326.             if (inputUri == null) {
  327.                 throw new ArgumentNullException("inputUri");
  328.             }
  329.             XmlReaderSettings rs = new XmlReaderSettings();
  330.             rs.ProhibitDtd = true;
  331.             return XmlReader.Create(inputUri, rs);
  332.         }
  333.        
  334.         //------------------------------------------------
  335.         // Test suites entry points
  336.         //------------------------------------------------
  337.        
  338.         private QilExpression TestCompile(object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
  339.         {
  340.             Reset();
  341.             CompileToQil(stylesheet, settings, stylesheetResolver);
  342.             return qil;
  343.         }
  344.        
  345.         private void TestGenerate(XsltSettings settings)
  346.         {
  347.             Debug.Assert(qil != null, "You must compile to Qil first");
  348.             CompileIlFromQil(settings);
  349.         }
  350.        
  351.         private void Transform(string inputUri, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver)
  352.         {
  353.             ((XmlILCommand)command).Execute(inputUri, documentResolver, arguments, results);
  354.         }
  355.        
  356.         static internal void PrintQil(object qil, XmlWriter xw, bool printComments, bool printTypes, bool printLineInfo)
  357.         {
  358.             QilExpression qilExpr = (QilExpression)qil;
  359.             QilXmlWriter.Options options = QilXmlWriter.Options.None;
  360.             QilValidationVisitor.Validate(qilExpr);
  361.             if (printComments)
  362.                 options |= QilXmlWriter.Options.Annotations;
  363.             if (printTypes)
  364.                 options |= QilXmlWriter.Options.TypeInfo;
  365.             if (printLineInfo)
  366.                 options |= QilXmlWriter.Options.LineInfo;
  367.             QilXmlWriter qw = new QilXmlWriter(xw, options);
  368.             qw.ToXml(qilExpr);
  369.             xw.Flush();
  370.         }
  371.     }
  372.     #endif // ! HIDE_XSL
  373. }

Developer Fusion