PhoenixmlDb.XSLT

XsltTransformer

Primary API for running XSLT transformations in .NET.

#XsltTransformer

Namespace: PhoenixmlDb.Xslt

Primary API for running XSLT transformations in .NET.

XsltTransformer provides a simple three-step workflow for XSLT processing: create an instance, load a stylesheet, and transform XML input. It supports XSLT 3.0 and 4.0 features including streaming, packages, higher-order functions, maps/arrays.

Invocation styles: XSLT defines three ways to start a transformation:

Thread safety: Instances are lightweight and not thread-safe. Create a new XsltTransformer for each transformation rather than sharing one across threads.

Basic usage:

csharp
var transformer = new XsltTransformer();
await transformer.LoadStylesheetAsync(myXsltString);
transformer.SetParameter("reportDate", "2025-01-15");
string result = await transformer.TransformAsync(inputXml);
                                  

Using initial-template invocation (no source document):

csharp
var transformer = new XsltTransformer();
await transformer.LoadStylesheetAsync(generatorStylesheet);
transformer.SetInitialTemplate("main");
string result = await transformer.TransformAsync(null);
                                  

#Properties

Name Description
AllowDtdProcessing Controls whether DTD processing is allowed when loading stylesheets. Default is false (DTDs are prohibited) for security.
HasStreamableMode True when the loaded stylesheet declares at least one streamable mode (either an explicit <xsl:mode streamable="yes"/> declaration or a streamable default mode). The CLI uses this signal to auto-select the streaming transform path for file inputs β€” non-streamable stylesheets always run on the materialising path. Returns false if no stylesheet is loaded yet.
MaxResultDocuments Maximum number of secondary result documents allowed per transformation. Default is 1000. Set to 0 for unlimited.
MessageListener Listener for xsl:message output. Receives the message text and a boolean indicating whether terminate="yes" was specified. When not set, messages are silently discarded.
MessageListenerWithLocation Extended listener for xsl:message that also receives source location (line, column). Takes precedence over XsltTransformer.MessageListener when set.
PreloadedResources Pre-fetched contents for URIs that xsl:import / xsl:include / fn:doc() would otherwise need to fetch over HTTP synchronously. Required on Blazor WebAssembly, which cannot block the calling thread; ignored on runtimes that can. Async-fetch the resources in your host code (via HttpClient with await or via JS interop) and assign before calling XsltTransformer.LoadStylesheetAsync. See XsltTransformer.PreloadedResources for a usage example.
ResourcePolicy Optional resource security policy. When set, controls which URIs the stylesheet can access via doc(), unparsed-text(), collection(), xsl:result-document, and xsl:import/xsl:include. See ResourcePolicy.ServerDefault for a secure server configuration.
ResultDocumentHandler Optional callback that provides a TextWriter for each secondary result document produced by xsl:result-document. When set, secondary documents are written directly to the provided writer instead of accumulating in XsltTransformer.SecondaryResultDocuments.
SchemaProvider Schema provider for schema-aware processing. Defaults to a fresh XsdSchemaProvider with no schemas loaded; any xsl:import-schema declarations encountered while loading a stylesheet are routed to this provider via ISchemaProvider.ImportSchema.
SecondaryResultDocuments Secondary result documents produced by xsl:result-document, keyed by the href attribute value.
TraceListener Sets a trace listener for debugging template matching, function calls, and built-in rule invocations during transformation.

#Methods

#AddInitialFunctionArgument(Object)

Adds a positional argument for the initial function call.

Parameters:

  • value β€” The argument value. Arguments are positional β€” add them in the same order as the xsl:param declarations in the target xsl:function.

Only used with call-function invocation (see

). Call this method once per function parameter, in declaration order.

#BuildTransformOptions(Boolean,PhoenixmlDb.Xslt.Engine.RawResultBox,Threading.CancellationToken)

Builds the

from the transformer's current configuration (parameters, initial-template / mode / function selection, listeners, resource policy, preloaded resources). Centralized so the four

TransformAsync

/

TransformToValueAsync

overloads stay in sync as new options are added.

#EnableXInclude(Boolean,PhoenixmlDb.Core.Xml.IXmlResourceResolver)

Enables XInclude 1.0 expansion of the principal source document. When on, any

xi:include

(

parse="xml"

) elements in the input passed to

are expanded before the document is transformed. Off by default.

Parameters:

  • allowRemote β€” When true, remote (http:/https:) include targets may be fetched. Defaults to false (only file:/relative targets resolve).

  • resolver β€” Optional host resolver for include targets; when null a built-in local-file resolver honoring allowRemote is used.

A source base URI is required so relative

href

s resolve β€” set it via

before transforming.

#ExtractNonNodeHeadFromSequence(PhoenixmlDb.Xdm.XdmSequence)

Returns the head item of

when it isn't an

β€” typically a map, array, atomic value or function-item produced by a previous transform's

parse-json

/

map:*

/

array:*

call. The caller routes node items through

instead.

#ExtractSourceFromSequence(PhoenixmlDb.Xdm.XdmSequence)

Pulls the first node item out of a sequence (to use as principal source) and the store backing the sequence's node items. Returns (null, null) for null or empty input β€” the transformation will run source-less.

#LoadStylesheetAsync(String,Uri,Collections.Generic.Dictionary<String,String>,Collections.Generic.Dictionary<String,Collections.Generic.List<ValueTuple<String,String>>>,PhoenixmlDb.Xslt.PackageVersionResolution)

Compiles and loads an XSLT stylesheet from its XML source text.

Parameters:

  • stylesheetXml β€” The complete XSLT stylesheet as an XML string. Must be well-formed XML with an xsl:stylesheet or xsl:transform root element.

  • baseUri β€” Base URI used to resolve relative references in xsl:import, xsl:include, and the doc() / document() functions. If null, relative URIs cannot be resolved and will cause an error.

  • staticParams β€” XSLT 3.0 static parameters (xsl:param with static="yes"). These are evaluated at compile time and can influence conditional compilation via xsl:use-when and static-params. Keys are parameter local names; values are string representations.

  • packageCatalog β€” Maps XSLT 3.0 package names to available versions and file paths, enabling xsl:use-package to locate and load package dependencies. Each key is a package name URI; the value is a list of (Version, FilePath) tuples.

  • packageVersionResolution β€” Policy for choosing among multiple package versions that satisfy an xsl:use-package/@package-version range. Defaults to PackageVersionResolution.Highest.

Returns: A completed task. The stylesheet is parsed synchronously.

Exceptions:

  • ArgumentNullException β€” stylesheetXml is null.

  • XsltException β€” The stylesheet contains syntax errors or invalid XSLT constructs.

#LooksLikeXml(String)

Heuristic: the result starts with a tag, suggesting XML markup.

#ParseExternalParamValue(String)

Same value-parsing heuristics as

StylesheetParser.PopulateExternalStaticParams

: recognise XPath-shaped literals, bare booleans, and numeric strings, falling through to

xs:untypedAtomic

for free-form strings. Keeps the runtime-side variable in sync with what the static-param resolver decided about the same value.

#ResolveSchemaImports(PhoenixmlDb.Xslt.Ast.XsltStylesheet,Uri)

Forwards every captured

xsl:import-schema

declaration to the registered

. Schema-location URIs are resolved against the stylesheet base URI before being handed to the provider so relative hints work.

#SetBaseOutputUri(Uri)

Sets the base output URI β€” where the principal result will be written (XSLT 3.0 Β§2.3).

Parameters:

  • uri β€” Absolute URI of the principal output destination.

This is what

fn:current-output-uri()

reports while the principal result is being produced, and what a relative

xsl:result-document/@href

resolves against. Leave it unset when the result has no URI β€” writing to stdout or to a string β€” in which case

current-output-uri()

correctly returns the empty sequence.

#SetCollection(String,Collections.Generic.List<String>)

Registers a named collection of document file paths, making them available to the XPath

fn:collection()

function during transformation.

Parameters:

  • uri β€” The collection URI that the stylesheet passes to fn:collection(). Use an empty string for the default collection (called with no arguments).

  • documentPaths β€” File system paths to XML documents that comprise the collection.

#SetInitialFunction(String,String)

Sets the initial function to call, using the XSLT 3.0 "call function" invocation style.

Parameters:

  • name β€” The function name. Must match a public xsl:function declared with visibility="public" (or the default visibility in XSLT 3.0).

  • namespaceUri β€” The namespace URI of the function. Stylesheet functions must be in a non-null namespace.

When using call-function invocation, supply arguments via XsltTransformer.AddInitialFunctionArgument in the order declared by the function's xsl:param elements. No source document is required β€” pass null to XsltTransformer.TransformAsync.

#SetInitialMode(String,String)

Sets the initial mode, determining which set of templates is applied to the source document.

Parameters:

  • mode β€” The mode name. Use "#unnamed" to explicitly select the unnamed (default) mode, or a specific mode name to select templates declared with that mode attribute.

  • namespaceUri β€” The namespace URI of the mode, or null for modes in no namespace.

Modes allow a stylesheet to define multiple sets of template rules for the same input nodes. For example, a stylesheet might have a "toc" mode for generating a table of contents and a default mode for the main output.

If no initial mode is set, the unnamed (default) mode is used. The stylesheet's xsl:stylesheet/@default-mode attribute can also influence this behavior.

#SetInitialModeSelect(String)

Sets an XPath expression to determine the initial match selection for the initial mode.

Parameters:

  • select β€” An XPath expression evaluated with the source document as context. Templates from the initial mode are applied to each item in the resulting sequence, rather than to the document root.

This corresponds to the XSLT 3.0 initial-match-selection concept. It allows you to apply templates to a computed set of nodes rather than the single root node. For example, "//chapter" would apply templates to every chapter element in the source document.

#SetInitialTemplate(String,String)

Sets the initial named template for call-template invocation.

Parameters:

  • name β€” The template name. For templates in a namespace, use either a prefixed name (e.g., "my:main") with the namespace URI in namespaceUri, or just the local name with the namespace URI.

  • namespaceUri β€” The namespace URI of the template, or null for templates in no namespace.

When an initial template is set, the transformation begins by calling that named template rather than applying templates to the source document. This means the inputXml parameter of XsltTransformer.TransformAsync can be null β€” the template generates output without needing a source document.

The conventional entry-point template name is "xsl:initial-template" (in the XSLT namespace), which is the XSLT 3.0 default initial template.

#SetInitialTemplateParameter(PhoenixmlDb.Core.QName,Object)

Sets an initial template parameter, passed via

xsl:with-param

to the initial template when using call-template invocation.

Parameters:

  • name β€” The qualified name matching an xsl:param in the initial template.

  • value β€” The value to bind to the parameter.

These parameters are distinct from stylesheet-level parameters set via

. They correspond to parameters declared inside the named template specified by

.

#SetInitialTunnelParameter(PhoenixmlDb.Core.QName,Object)

Sets an initial template tunnel parameter, which propagates through the call chain without being explicitly declared at each level.

Parameters:

  • name β€” The qualified name of the tunnel parameter.

  • value β€” The value to bind to the tunnel parameter.

Tunnel parameters are an XSLT 2.0+ feature that allows values to "tunnel" through intermediate template calls to deeply nested templates that declare matching

xsl:param tunnel="yes"

parameters.

#SetParameter(PhoenixmlDb.Core.QName,Object)

Sets a global stylesheet parameter whose name is NAMESPACED, preserving its typed value.

Parameters:

  • name β€” The qualified name of a top-level xsl:param. Pass a QName rather than a string: the string overloads take a LOCAL name and have no spelling for a namespace.

  • value β€” The typed value to bind, or null for the empty sequence.

#SetParameter(String,Object)

Sets a stylesheet parameter with a typed value, preserving its XDM type.

Parameters:

  • name β€” The local name of an xsl:param declared at the top level of the stylesheet.

  • value β€” The typed value to bind. .NET types are mapped to XDM types: Int32 and Int64 become xs:integer, Double becomes xs:double, Boolean becomes xs:boolean, Decimal becomes xs:decimal, and String becomes xs:untypedAtomic. Pass null to set the parameter to an empty sequence.

Parameters must match

xsl:param

declarations in the stylesheet. If the stylesheet declares a parameter with

as="xs:integer"

and you supply a string, a type error will occur at runtime.

#SetParameter(String,String)

Sets a stylesheet parameter with a string value.

Parameters:

  • name β€” The local name of an xsl:param declared at the top level of the stylesheet.

  • value β€” The string value to bind. The value is supplied as xs:untypedAtomic, which means it will be automatically promoted during comparisons β€” for example, comparing it to an xs:double will succeed without an explicit cast.

If you need the parameter to carry a specific XDM type (e.g., xs:integer or xs:boolean), use the XsltTransformer.SetParameter overload with a typed .NET value such as Int32 or Boolean.

#SetSourceDocumentUri(Uri)

Sets the URI of the source document, used for

base-uri()

and

document-uri()

resolution during transformation.

Parameters:

  • uri β€” The URI to associate with the source document. This does not load the document from the URI β€” it only sets the base URI metadata on the document node created from the inputXml string passed to XsltTransformer.TransformAsync.

Setting a source document URI is important when the stylesheet uses relative URIs in

doc()

or

document()

calls that should resolve relative to the source document's location rather than the stylesheet's base URI.

#SetSourceSelect(String)

Sets an XPath expression to select the initial context node from the source document.

Parameters:

  • select β€” An XPath expression evaluated against the source document. The result becomes the initial context item for the transformation. For example, "/doc" selects the document element named doc instead of the document root node.

By default, the initial context item is the document node (root) of the source document. Use this method when the stylesheet expects a specific element or node as its starting context rather than the root.

#TransformAsync(IO.Stream,IO.Stream,Threading.CancellationToken)

Transforms XML from a

and writes to a

. When the loaded stylesheet's initial mode is streamable, the input stream is fed directly to the streaming engine without an intervening

ReadToEndAsync

, bounding peak memory. Non-streaming stylesheets retain the original buffered path.

#TransformAsync(IO.Stream,IO.TextWriter,Threading.CancellationToken)

Streams XML from a

and writes the serialized primary result incrementally to a

. Requires the stylesheet's initial mode to be streamable; otherwise an

is thrown by the engine.

Cancellation is not transactional β€” content already delivered to

before cancellation cannot be retracted.

#TransformAsync(IO.Stream,Threading.CancellationToken)

Transforms XML from a

source.

#TransformAsync(IO.TextReader,IO.TextWriter,Threading.CancellationToken)

Transforms XML from a

and writes to a

.

#TransformAsync(IO.TextReader,Threading.CancellationToken)

Transforms XML from a

source.

#TransformAsync(PhoenixmlDb.Xdm.XdmSequence,Threading.CancellationToken)

Transforms an

source β€” pass the typed result of one transformation directly into another, without serializing through XML markup. The engine reads the sequence's backing

Store

to navigate any node items.

When source is null or empty, the transformation runs without a principal source document β€” appropriate for xsl:initial-template / xsl:initial-function invocation. Otherwise the first node item in the sequence becomes the principal source.

If the sequence contains node items, its XdmSequence.Store must be a compatible XdmInMemoryStore β€” typically a sequence produced by a previous call to XsltTransformer.TransformToSequenceAsync.

#TransformAsync(String,IO.TextWriter,Threading.CancellationToken)

Transforms XML and writes the primary result to a

.

#TransformAsync(String,Threading.CancellationToken)

Transforms an XML string using the loaded stylesheet and returns the serialized primary result document.

Parameters:

  • inputXml β€” The source XML document to transform, or null when using call-template or call-function invocation that does not require a source document. When null, an empty placeholder document is used internally.

  • ct β€” Cancellation token for aborting long-running transformations. When cancelled, an OperationCanceledException is thrown.

Returns: The serialized primary result document as a string. The serialization format (XML, HTML, text, JSON, or adaptive) is determined by the stylesheet's xsl:output declaration.

Exceptions:

  • InvalidOperationException β€” No stylesheet has been loaded. Call XsltTransformer.LoadStylesheetAsync first.

  • XsltException β€” A runtime error occurred during transformation, such as a type error, missing template, or evaluation failure.

  • OperationCanceledException β€” The ct cancellation token was triggered.

After this method returns, any secondary outputs produced by xsl:result-document instructions are available in XsltTransformer.SecondaryResultDocuments.

#TransformToSequenceAsync(PhoenixmlDb.Xdm.XdmSequence,Threading.CancellationToken)

Transforms an

and returns the raw XDM result wrapped in another

that carries the engine's node-store, so the result can be passed directly to another

or XQuery call without serialization.

#TransformToValueAsync(String,Threading.CancellationToken)

Transforms

and returns the RAW XDM value of the transformation β€” the typed result (xs:boolean, xs:integer, map, array, node, …) preserved end-to-end, not serialized to a string and reparsed. Used by

fn:transform()

with

delivery-format='raw'

from XQuery, where the caller wants to consume the typed result directly rather than as XML markup. Currently only honored when the transformation is invoked via

(the only case where there's a single well-defined return value); template-based invocations still serialize.

Returns: The raw XDM value: a single item, an object?[] for sequences, or null for the empty sequence.

#TryParseToXdmDocument(String,PhoenixmlDb.Xslt.XdmInMemoryStore)

Parses serialized XML markup into an

registered with

. Returns null if parsing fails (the caller falls back to keeping the raw string).

#Fields

Name Description
_typedParametersByQName Global parameters supplied by QNAME rather than by local name. Separate from _typedParameters because that one is keyed by the string a caller passed and is wrapped as a no-namespace QName; there is no string spelling of a namespaced name that survives that wrapping.

#See also

  • XsltException