BizTalk Utilities CV ,   Jobs ,   Code library
 
Go to the front page to continue learning about XML or select below:

Contents

ReBlogger Contents

Previous posts in WS, web services

 
 
Page 16899 of 21350

Migrating to XslCompiledTransform

Blogger : XmlTeams WebLog
All posts : All posts by XmlTeams WebLog
Category : WS, web services
Blogged date : 2005 Sep 30

Migrating to XslCompiledTransform

To improve XSLT execution performance in the .NET Framework version 2.0, the XslTransform class has been replaced with a new XSLT 1.0 implementation: the XslCompiledTransform class. XslCompiledTransform compiles XSLT stylesheets to Microsoft Intermediate Language (MSIL) methods and then executes them. Execution time of the new processor is on average 4 times better than XslTransform and matches the speed of MSXML, the native XML processor.

Although XslCompiledTransform is designed to be as compatible with XslTransform as possible, differences between the two classes nonetheless exist. The purpose of this document is to cover known differences between XslTransform to XslCompiledTransform and to simplify migration from the former to the latter.

How XslCompiledTransform Works

Before we can talk about migration, its worth briefly outlining how XCT works.

Loading the Stylesheet

When the Load() method is called, XslCompiledTransform reads stylesheets from XmlReader and creates an abstract syntax tree (AST)of the principal stylesheet and all its imports and includes. It then compiles all script blocks to assemblies (one assembly per namespace). Finally it compiles the AST to a separate assembly.

Performing the Transformation

Once the stylesheets are loaded, XslCompiledTransform can transform the input document. Transformation of the input document to output involves the following steps:

1.      Building the XML tree for input document (cache).

2.      Converting input XML tree to output tree.

3.      Serialization of output tree.

To load the cache, XslCompiledTransform uses XmlReader to read the input document. At this time, XslCompiledTransform applies whitespace stripping rules.

If the input document was specified as a URI string, XslCompiledTransform creates an XmlReader to read the XML document from this URI using default XmlReaderSettings, but allowing Document Type Definition (DTD):

        XmlReaderSettings rs = new XmlReaderSettings();

        rs.ProhibitDtd = false;

        XmlReader.Create(inputUri, rs);

If the input document was specified as IXPathNavigable, XslCompiledTransform doesnt reload the cache. It calls IXPathNavigable.CreateNavigator() and uses this navigator as its cache. In this case, if the stylesheet has xsl:strip-spase or xsl:preserve-space instructions, XslCompiledTransform raises an error because it can`t properly apply whitespace-stripping rules.

Transformation is started by applying all template rules to the current node in the XML tree. In most cases the current node will be the root node (one that matches pattern /). XslCompiledTransform allows user to choose what node should be current at transformation start by providing input document as XPathNavigator positioned to this node. Values of global variables will be calculated lazily (on first use) and context node for them will always be root node even when transformation was started from other node.

This behavior is key to allowing users to rerun parts of the transformation. XslTransform, by contrast, doesnt support this feature. It always starts transformation from the root node. 

Depending on the Transform() overload called, users may receive transformation results in one of these forms: Stream, TextWriter, XmlWriter, or XmlReader. Internally, Transform() always generates output as a set of XmlWriter events and then serializes these events to the requested form.

The stylesheet may contain one or more xsl:output instructions that specify how output should be serialized. These instructions are compiled to XmlWriterSettings class and are available to the user via the OutputSettings property of XslCompiledTransform. Users may receive the output tree directly by providing an instance of the XmlWriter class to the Transform() method as the results argument. In this case the user is responsible for output serialization. When Transform() is called with Stream or TextWriter as the result argument, XslCompiledTransform internally creates XmlWriter by calling XmlWriter.Create(result, outputSettings) and then uses this writer to serialize transformation output.

 

API Changes

Below are the methods and functions of the XslTransform and XslCompiledTransform classes, respectively.

XslTransform Class

public sealed class XslTransform {

    public XslTransform();

 

    public XmlResolver XmlResolver { set ; }

 

    public void Load(XmlReader stylesheet);

    public void Load(XmlReader stylesheet, XmlResolver resolver);

    public void Load(IXPathNavigable stylesheet);

    public void Load(IXPathNavigable stylesheet, XmlResolver resolver);

    public void Load(XPathNavigator stylesheet);

    public void Load(XPathNavigator stylesheet, XmlResolver resolver);

    public void Load(string url);

    public void Load(string url, XmlResolver resolver);

    public void Load(IXPathNavigable stylesheet, XmlResolver resolver, Evidence evidence);

    public void Load(XmlReader stylesheet, XmlResolver resolver, Evidence evidence);

    public void Load(XPathNavigator stylesheet, XmlResolver resolver, Evidence evidence);

 

    public XmlReader Transform(XPathNavigator input, XsltArgumentList args, XmlResolver resolver);

    public XmlReader Transform(XPathNavigator input, XsltArgumentList args);

    public void Transform(XPathNavigator input, XsltArgumentList args, XmlWriter output, XmlResolver resolver);

    public void Transform(XPathNavigator input, XsltArgumentList args, XmlWriter output);

    public void Transform(XPathNavigator input, XsltArgumentList args, Stream output, XmlResolver resolver);

    public void Transform(XPathNavigator input, XsltArgumentList args, Stream output);

    public void Transform(XPathNavigator input, XsltArgumentList args, TextWriter output, XmlResolver resolver);

    public void Transform(XPathNavigator input, XsltArgumentList args, TextWriter output);

    public XmlReader Transform(IXPathNavigable input, XsltArgumentList args, XmlResolver resolver);

    public XmlReader Transform(IXPathNavigable input, XsltArgumentList args);

    public void Transform(IXPathNavigable input, XsltArgumentList args, TextWriter output, XmlResolver resolver);

    public void Transform(IXPathNavigable input, XsltArgumentList args, TextWriter output);

    public void Transform(IXPathNavigable input, XsltArgumentList args, Stream output, XmlResolver resolver);

    public void Transform(IXPathNavigable input, XsltArgumentList args, Stream output);

    public void Transform(IXPathNavigable input, XsltArgumentList args, XmlWriter output, XmlResolver resolver);

    public void Transform(IXPathNavigable input, XsltArgumentList args, XmlWriter output);

    public void Transform(String inputfile, String outputfile, XmlResolver resolver);

    public void Transform(String inputfile, String outputfile);

}

XslCompiledTransform Class

public sealed class XslCompiledTransform {

    public XslCompiledTransform() {}

    public XslCompiledTransform(bool enableDebug);

 

    public XmlWriterSettings  OutputSettings { get; }

    public TempFileCollection TemporaryFiles { get; }

 

    public void Load(XmlReader stylesheet);

    public void Load(XmlReader stylesheet, XsltSettings settings, XmlResolver stylesheetResolver);

    public void Load(IXPathNavigable stylesheet);

    public void Load(IXPathNavigable stylesheet, XsltSettings settings, XmlResolver stylesheetResolver);

    public void Load(string stylesheetUri);

    public void Load(string stylesheetUri, XsltSettings settings, XmlResolver stylesheetResolver);

 

    public void Transform(IXPathNavigable input, XmlWriter results);

    public void Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results);

    public void Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results);

    public void Transform(IXPathNavigable input, XsltArgumentList arguments, Stream results);

    public void Transform(XmlReader input, XmlWriter results);

    public void Transform(XmlReader input, XsltArgumentList arguments, XmlWriter results);

    public void Transform(XmlReader input, XsltArgumentList arguments, TextWriter results);

    public void Transform(XmlReader input, XsltArgumentList arguments, Stream results);

    public void Transform(XmlReader input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver);

    public void Transform(string inputUri, string resultsFile);

    public void Transform(string inputUri, XmlWriter results);

    public void Transform(string inputUri, XsltArgumentList arguments, XmlWriter results);

    public void Transform(string inputUri, XsltArgumentList arguments, TextWriter results);

    public void Transform(string inputUri, XsltArgumentList arguments, Stream results);

}

 

As you can see, the APIs of the classes are very similar. The major differences are:

        Load() overloads that take Evidence have been replaced by ones taking XsltSettings.

        XslCompiledTransform omits the Transform() overload that returns XmlReader.

        XslCompiledTransform introduces two new properties, OutputSettings and TemporaryFiles, and one additional constructor taking the enableDebug flag.

Let`s discuss each of these in turn.

Outputting transformation results to XmlReader

In most cases, the user wants receive results of transformation in from of XmlReader to load them to cache: XmlDocument or XPathDocument.

For example,

XmlDocument doc  = new XmlDocument();

doc.Load(xsl.Transform(input, /*args:*/null));

 

This scenario is especially important because transformation results can be cached without incurring the overhead of serialization and deserialization.

Although XslTransform can produce output in the form of XmlReader, for performance reasons, this feature wasnt implemented in XslCompiledTransform. To support this scenario with XslCompiledTransform, XmlNavigator now provides methods for loading cache from XmlWriter. The same scenario will now look like:

XmlDocument doc = new XmlDocument();

xslt.Transform(input, /*args:*/null, doc.CreateNavigator().AppendChild());

 

XmlReader may be required for other reasons than caching transformation results. Such scenarios are rare, but it is worth mentioning how to address them. When transformation output is expected to be small (less than a megabyte), the simplest and fastest way to produce a reader will be caching transformation results and creating an XmlReader over this cache:

XmlDocument doc = new XmlDocument();

xslt.Transform(input, /*args:*/null, doc.CreateNavigator().AppendChild());

XmlReader reader = doc.CreateNavigator().ReadSubtree();

 

If transform output is expected to be large, caching its results to XmlDocument may not perform well. Another approach to solve this problem is to use XslReader class which impelemts XmlReader by running XslCompiledTransform on a separate thread and resuming this thread each time XmlReader.Read() needs a next node.

(XslReader is still under development. It will be available in sources on GotDotNet.)


Ensuring Security: XsltSettings Class

Instead of Evidences, new API uses XsltSettings to control stylesheet rights.

XsltSettings is a new class introduced in .NET Framework 2.0 to control XSLT compilation. XsltSettings exposes two properties: EnableScript and EnableDocumentFunction.

 

    public sealed class XsltSettings {

        public XsltSettings();

        public XsltSettings(bool enableDocumentFunction, bool enableScript);

 

        public bool EnableDocumentFunction { get; set; }

        public bool EnableScript { get; set; }

 

        public static XsltSettings Default {

            get { return new XsltSettings(false, false); }

        }

 

        public static XsltSettings TrustedXslt {

            get { return new XsltSettings(true, true); }

        }

    }

 

Script blocks and the document() function may introduce security risks and are thus disabled by default. If you trust the stylesheet and want to use those features, you need to explicitly enable them by passing an appropriately set XsltSettings object, as shown below:

 

    XslCompiledTransform xslt = new XslCompiledTransform();

 

    // Disable script blocks and the document() function if a stylesheet came from an untrusted source

    xslt.Load(@"http://untrusted.site.com/mew.xsl", XsltSettings.Default, new XmlUrlResolver());

 

    // Enable script blocks and the document() function if a trusted stylesheet needs them

    xslt.Load(@"C:\MyProject\purr.xsl", XsltSettings.TrustedXslt, new XmlUrlResolver());

 

Overloads of the Load() method that do not take an XsltSettings argument, will use XsltSettings.Default.

Cleanup: TemporaryFiles Property

If a stylesheet contains script blocks, or it is compiled with the enableDebug flag set to true, XslCompiledTransform may create some temporary files in the %TEMP% folder. When the finalizer of a TempFileCollection object (which keeps track of created temporary files), tries to remove all of them, some files may be in use by the current AppDomain (*.DLL files) or by the debugger (*.PDB files). Those files cannot be deleted until unloading the AppDomain or detaching the debugger. If you frequently compile XSLT stylesheets with script blocks, the %TEMP% folder may become overcrowded with temporary files left undeleted. To ensure that all temporary files will be removed, an advanced client may use the TemporaryFiles property to save paths of temporary files for a further cleanup.

Respecting xsl:output: OutputSettings property

When a user calls the Transform() overload with XmlWriter as result argument, XsltCompiledTransform ignores all stylesheet serialization hints from the xsl:output element. In this case the user is responsible for output serialization. The user can control serialization by writing custom subclasses of XmlWriter or by adjusting the properties of XmlTextWriter.

In either case, the user may want to know what serialization settings a stylesheet has. XslCompiledTranform exposes this information in the OutputSettings property.

The following example XmlWriter uses the same settings from the original stylesheet, but turns character checking off:

XslCompiledTransform transform = new XslCompiledTransform();

transform.Load("MyStylesheet.xsl");

XmlWriterSettings ws = transform.OutputSettings.Clone();

ws.CheckCharacters = false;

transform.Transform("MyDocument.xml", XmlWriter.Create(Console.Out, ws));

 

Differences in behavior

Discretionary Behaviors

For a number of error cases, the XSLT specification leaves XSLT processors flexibility to either signal an error, or recover by taking certain recovery action. The table below summarizes behaviors of XslTransform and XslCompiledTransform in such cases.

 

Error description

Section

XslTransform

XslCompiledTransform

A source node matches to both xsl:strip-space and xsl:preserve-space elements, and the conflict cannot be resolved

3.4

Recover

Recover

A source node matches more than one template rule, and the conflict cannot be resolved

5.5

Recover

Recover

A namespace URI is declared to be an alias for multiple different namespace URIs with the same highest import precedence

7.1.1

Recover

Recover

The effective value of the name attribute of xsl:attribute or xsl:element is not a valid QName

7.1.2, 7.1.3

Error

Error

Adding an attribute to an element after children have been added to it

7.1.3

Recover

Error

Creating an attribute with the name "xmlns"

7.1.3

Recover

Error

Adding an attribute to a node that is not an element

7.1.3

Recover

Error

Creating nodes other than text nodes during the instantiation of the content of the xsl:attribute element.

7.1.3

Recover

Error

Two attribute set definitions with the same expanded-name and the same highest import precedence contain an attribute in common

7.1.4

Recover

Recover

The effective value of the name attribute of the xsl:processing-instruction element is not both a NCName and a PITarget

7.3

Recover

Error

Instantating the content of xsl:processing-instruction creates nodes other than text nodes

7.3

Recover

Error

The result of instantiating the content of the xsl:processing-instruction contains the string ">"

7.3

Recover

Recover

The result of instantiating the content of the xsl:processing-instruction contains the string "--" or ends with "-"

7.4

Recover

Recover

The result of instantiating the content of the xsl:comment creates nodes other than text nodes

7.4

Recover

Error

The sequence of nodes created by instantiating the template within a variable-binding element contains an attribute node or a namespace node

11.2

Recover

Error

There is an error retrieving the resource from the URI passed into the document function

12.1

Recover

Error

The URI reference in the document function contains a fragment identifier and there is an error processing the fragment identifier

12.1

Fragment identifiers are ignored

Fragment identifiers are ignored

There are multiple attributes with the same name that are not named cdata-section-elements in xsl:output with the same import precedence

16

Recover

Recover

The encoding specified in the encoding attribute of the xsl:output element is not supported

16.1

Recover

Recover

Disabling output escaping for a text node that is used for something other than a text node in the result tree

16.4

Recover

Recover

Converting a result tree fragment to a number or string if the result tree fragment contains a text node with output escaping enabled.

16.4

Recover

Recover

Output escaping is disabled for a character that is not representable in the encoding that the XSLT processor is using for output

16.4

Recover

Recover

Adding a namespace node to an element after children have been added to it or after attributes have been added to it

E25

Recover

Error

The effective value of the value attribute of the xsl:number element is NaN, infinite, or less than 0.5

E24

Recover

Recover

The second argument node-set to the document() function is empty and the URI reference is relative

E14

Recover

Recover

 

TBD: key() function with invalid key name. Extension function returned null or an object of an unsupported type. Overloads.

New XPath Engine

TBD

Loading Stylesheets and Source Documents

In XSLT both stylesheets and source documents are XML files. There is a lot of similarity in loading them. Here we summarize how XslCompiledTransform loads stylesheets and source documents and then we will see where its behavior is different from XslTransform.

 XslCompiledTransform uses XmlReader to read both stylesheets and source documents. In both cases more then one XML file can be used. Stylesheets can have xsl:include/import to load another stylesheet; to load additional source documents, the document() function can be used.

XslCompiledTransform delegates all work related to external URIs access to  XmlResolver. To load the principal stylesheet and all includes/imports, XslCompiledTransform uses instance of XmlResolver which was passed to the Load() method. To load the source document and all subsequent documents, XslCompiledTransform uses XmlResolver passed to the Transform() method.

When the overload of the Load()/Transform() method that doesnt have XmlResolver argument is called, XmlUrlResolver is used to load subsequent stylesheets and documents. When null is passed as an XmlResolver argument to the Load()/Transform() method, loading of subsequent stylesheets/documents is disabled.

(TBD: This is XslCompiledTransfor behavior. How it relates to XslTransform)

Whitespace Handling

Users can pass XmlReader, Uri or XPathNavigator to Load()/Transform() methods. Uri will be passed to XmlResolver and resolved to XmlReader, TextReader, Stream or XPathNavigator.

For subsequent stylesheets/documents XmlResolver returns to Proccessor XmlReader, TextReader, Stream or XPathNavigator.

In case when input is TextReader or Stream to load XML Processor creates XmlTextReader. XmlTextReader has set of properties which control readers behavior. (Most important properties are Normalization, ProhibitDtd, WhitespaceHandling, XmlResolver; see documentation for XmlTextReader on meaning of this properies.)

When XslCompiledTransform creates the first reader, one that is used for reading data passed directly to Load()/Transform() methods, it sets the reader setting the following way:

XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();

xmlReaderSettings.NameTable = xmlNameTable;

xmlReaderSettings.ConformanceLevel = ConformanceLevel.Document;

xmlReaderSettings.XmlResolver = null;

xmlReaderSettings.ProhibitDtd = true;

xmlReaderSettings.CloseInput = true;

 

For each subsequent stylesheet/document XslCompiledTransform creates XmlTextReader with the same reader settings that the first XmlReader has. This guarantees consistency in loading stylesheets and source documents.

If the user wants to use specific reader settings in stylesheet/document load process, he should pass XmlReader created with these settings to Load()/Transform() methods. If the user wants XmlReader for subsequent stylesheet/document document to have different reader settings, he should pass as an argument to a Load()/Transform() custom XmlResolver, which returns XmlReader with required reader settings.

 

In contrast, XslTransform always created XmlReader as new XmlReader() and is user passes non-default reader to Load()Transform() methods reader settings for subsequent readers may differ from reader settings of original reader.

document() Function

XslTransform swallowed any exceptions thrown during execution of the document() function, returning an empty node-set. All possible run-time errors (e.g., network share cannot be accessed) were masked, and users had no means to control that.

In contrast, XslCompiledTransform class does not swallow exceptions, but instead propagates them wrapped in an XslTransformException. However, you can still implement XslTransforms behaviorif the GetEntity() method of your custom XmlResolver returns null, it is treated as an empty node-set, and no errors will be reported.

If you use XslTransform, the GetEntity() method of your XmlResolver has to return either Stream or XPathNavigator. XslCompiledTransform, by contrast, can return either Stream, XmlReader, or IXPathNavigable (and, therefore, XPathNavigator). The option of returning XmlReader is useful if you want to have precise control of loading documents, for example, to control whitespace handling, DTD handling (prohibit or allow processing a DTD), compatibility issues (use an old XmlTextReader or a new reader created by XmlReader.Create()), etc.

It is common to use document(``) to refer to the document node of the containing stylesheet module. Please note that the base URI of the stylesheet module must be known in order to make it work. For example, if you create an XmlReader over a stream without specifying a base URI, XSLT engine will not resolve the empty string reference correctly unless you have provided a custom XmlResolver that handles such a reference in a special way.

Extension Objects and Script Functions

With both XslCompiledTransform and with XslTransform, the user can extend XSLT language by either adding extension to XsltArgumentList or by adding script blocks to the stylesheet. Here we outline differences between XslTransform and XslCompiledTransform in using these features.

Transform uses CodeDom to compile script blocks (msxsl:script elements). It compiles all script blocks with the same namespace as one class by inserting all code snippets to the same CodeTypeDeclaration. Methods of this class will be visible from XPath expressions in the stylesheet.

There are two new restrictions in use of scripts in XslCompiledTransform:

        Only public methods are visible.

        Overloads are distinct only base on number of arguments. If more then one overload has the same number of arguments, an exception will be raised.

In XslCompiledTransform a binding (method name lookup) to script functions happens at compile time, and stylesheets that are compliable with XslTranform may throw an exception during compilation with XslCompiledTransform.

msxsl:script allows two child elements now, msxsl:using and msxsl:assembly, to add in scope namespace and refer additional assembly, respectively.

The only difference in implementation of extension objects is that multiple overloads with the same number of arguments are prohibited now.

Returning a Node-Set

XslTransform allowed returning a node-set from an extension function as an object of the XPathNodeIterator class With XslCompiledTransform, by contrast, you have more alternatives: a node-set may be returned as XPathNodeIterator, XPathNavigator[], or XPathNavigator (if the node-set consists of a single node).

xsl:message

TBD: XsltArgumentList.XsltMessageEncountered

xsl:sort

TBD: different sets of languages supported.

ms:script

TBD: different sets of language names supported. New CodeDom activation technology.

Base URI of an RTF

TBD: Now RTFs have correct base URIs.

Better Compatibility with MSXML

XslCompiledTransform makes it easier to migrate from MSXML to managed XSLT implementation by supporting some MSXML extensions. Everywhere in this section the ms prefix denotes the urn:schemas-microsoft-com:xslt namespace URI. Another frequently used prefix for this namespace URI is msxsl. Of course, you may use any other prefix in your stylesheet provided it is bound to the same URI.

ms:node-set() Function

XslTransform required the argument of the ms:node-set() function to be an RTF (result tree fragment), throwing an exception for an argument of any other type. Behavior of this function in XslCompiledTransform is now aligned with the behavior of MSXML and exsl:node-set(), which allow converting a value of an arbitrary type into a text node containing a string representation of that value. For example, ms:node-set(1 div 0) will create a text node with the value Infinity.

ms:version system Property

XslTransform did not recognize the ms:version property, returning an empty string. XslCompiledTransform supports the ms:version system property. For example, system-property(`ms:version`) returns a string representing the version of the assembly implementing XslCompiledTransform in the same format as returned by Assembly.ImageRuntimeVersion property (for example, v2.0.50720).

XPath Extension Functions

MSXML provides a number of XPath extension functions to facilitate developing XSLT stylesheets. XslCompiledTransform supports all those functions except schema-related ones:

 

Function

Signature and description

ms:string-compare

number ms:string-compare(string x, string y[, string language[, string options]])

Performs lexicographical string comparison.

ms:utc

string ms:utc(string time)

Converts the prefixed date/time related values into Coordinated Universal Time and into a fixed (normalized) representation that can be sorted and compared lexicographically.

ms:namespace-uri

string ms:namespace-uri(string name)

Resolves the prefix part of a qualified name into a namespace URI.

ms:local-name

string ms:local-name(string name)

Returns the local name part of a qualified name by stripping out the namespace prefix.

ms:number

number ms:number(string value)

Takes a string argument in XSD format and converts it into an XPath number.

ms:format-date

string ms:format-date(string datetime[, string format[, locale]])

Converts standard XSD date formats to characters suitable for output.

ms:format-time

string ms:format-time(string datetime[, string format[, locale]])

Converts standard XSD time formats to characters suitable for output.

 

The following schema-related XPath extension functions are not supported natively by XslCompiledTransform, but may be implemented as extension functions:

 

Function

Signature and description

ms:type-is

boolean ms:type-is(string URI, string local-name)

Compares the current node`s data type against the specified node type.

ms:type-local-name

string ms:type-local-name([node-set nodes])

Returns the nonqualified name of the XSD type of the current node or the first node (in document order) in the provided node-set.

ms:type-namespace-uri

string ms:type-namespace-uri([node-set nodes])

Returns the namespace URI associated with the XSD type of the current node or the first node (in document order) in the provided node-set.

ms:schema-info-available

boolean ms:schema-info-available()

Returns true if XSD information is available for the current node.

 

ms:script

If you migrate from MSXML, and your stylesheets contain script blocks, you will likely have to rework them, because System.Xml uses a different object model to represent nodes and node-sets than MSXML does. Moreover, managed Jscript .NET and Visual Basic .NET, supported by XslCompiledTransform, differ to some extent from their native counterparts, JScript and VBScript.

In the .NET Framework 2.0, this gap is narrowed a bit. XPathNodeIterator implements the IEnumerable interface. This allows iterating node-set objects with Jscripts foreach expression.

FAQ

How do I specify a starting mode

With MSXML you can specify an initial mode, which the transformation would start in, using the setStartMode method of the IXSLProcessor interface. Both XslTransform and XslCompiledTransform do not provide means to specify a start mode, however you may simulate that by passing the name of the start mode as an additional parameter to your stylesheet and adding a new start template containing a switch table:

 

:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    :import href="main.xsl"/>
 
    
    :param name="start-mode" select="``"/>
 
    :template match="/">
        
        :choose>
            :when test="$start-mode=``">
                
                :apply-imports/>
            :when>
            :when test="$start-mode=`foo`">
                
                :apply-templates select="/" mode="foo"/>
            :when>
            :when test="$start-mode=`bar`">
                
                :apply-templates select="/" mode="bar"/>
            :when>
            ...
            :otherwise>
                :message terminate="yes">Invalid start-mode:message>
            :otherwise>
        :choose>
    xsl:template>
xsl:stylesheet>

Why is System.Data.SqlXml on the stack

You may be surprised at seeing System.Data.SqlXml assembly on a call stack. System.Data.SqlXml is a helper assembly containing XslCompiledTransform implementation. It is not supposed to be used directly, and there is no guarantee that its API will not be changed in future .NET Framework releases.

 

Authors: Sergey Dubinets, Anton Lapunov


Read comments or post a reply to : Migrating to XslCompiledTransform
Page 16899 of 21350

Newest posts
 

    Email TopXML