API Reference

The XSLTProcessor class implements the W3C/MDN XSLTProcessor API and adds transformToString() plus stylesheet and document loaders. This page covers its methods, parameters, xsl:output serialization, the module exports, the XsltEngine options and the TypeScript declarations. Loaders for xsl:import, xsl:include and document() are described in Loaders.

Contents

XSLTProcessor

Constructor

const processor = new XSLTProcessor();

Methods

MethodDescription
importStylesheet(node, stylesheetUri?)Imports an XSLT stylesheet from a Document or Element node. The optional stylesheetUri is the base URI used to resolve relative xsl:import/xsl:include hrefs
transformToFragment(source, output)Transforms XML and returns a DocumentFragment owned by output
transformToDocument(source)Transforms XML and returns an XMLDocument
transformToString(source)Transforms XML and returns the serialized result honoring xsl:output (non-W3C extension)
setParameter(namespaceURI, localName, value)Sets an XSLT parameter
getParameter(namespaceURI, localName)Gets an XSLT parameter value ('' when it is not set)
removeParameter(namespaceURI, localName)Removes an XSLT parameter
clearParameters()Removes all parameters
reset()Resets the processor, removing stylesheet and parameters (the stylesheet and document loaders are kept)
setStylesheetLoader(loader)Sets the loader used to resolve xsl:import/xsl:include (non-W3C extension). Pass null to remove it. Returns the processor for chaining
setDocumentLoader(loader)Sets the loader used to resolve the XSLT document() function (non-W3C extension). Pass null to remove it. Returns the processor for chaining

Like the native implementation, the transformTo* methods return null when the transformation fails (for example xsl:message terminate="yes") and log the error with console.error. Missing arguments, a source that is not a Document, Element or DocumentFragment, and calling them before importStylesheet() throw instead.

importStylesheet() throws for a stylesheet that is not valid XSLT 1.0, for example an invalid pattern such as match="a/.." (the error names the pattern), as Chrome's native processor rejects such stylesheets. The processor then keeps its previously imported stylesheet. Invalid names computed at run time by xsl:element/xsl:attribute are reported with console.warn and skipped, as libxslt does.

Properties

PropertyDescription
engineRead-only access to the underlying XsltEngine (advanced usage). It is null until importStylesheet() has been called

Module exports

ExportDescription
XSLTProcessor (also the default export)The processor class described above
isNativeXSLTSupported()true when globalThis.XSLTProcessor exists and transforms a test document. After installGlobal() it tests the installed polyfill
installGlobal(force = false)Sets globalThis.XSLTProcessor to this implementation when native XSLT is not functional (always with force). Returns true when installed
serializeResult(node, outputSettings?)Serializes a document, fragment or element with xsl:output settings, see below
resolveOutputSettings(outputSettings, node)Normalizes raw xsl:output settings (booleans for indent/omitXmlDeclaration, a Set of CDATA element names, detected method)
markRawText(textNode), isRawText(node)Mark / test a text node that is serialized without escaping (disable-output-escaping)
evaluateXPath(expr, node, { variables, namespaces }?)Evaluates an XPath 1.0 expression; returns a node array, string, number or boolean
selectXPath(expr, node, options?)Returns the matching nodes as an array ([] for non node-set results)
selectFirstXPath(expr, node, options?)Returns the first matching node or null
parseXPath(expr)Parses an expression into the AST accepted by XPathEvaluator#evaluate
XPathEvaluator, XPathContextLow-level XPath API, see Custom Security Limits
XPathResultTypeThe DOM XPathResult type constants (ANY_TYPE ... FIRST_ORDERED_NODE_TYPE)
XsltEngine, XsltContextThe engine behind XSLTProcessor (advanced usage)
XSLT_MAX_RESULT_SIZE, XSLT_MAX_EXPRESSION_DEPTHDefault XPath limits inside a transformation (5,000,000 and 1000)
VERSIONThe package version, e.g. '1.1.3'
isBrowser, isNodeEnvironment flags evaluated at load time

TypeScript

Declarations ship as dist/xslt-processor.d.ts (ESM) and dist/xslt-processor.d.cts (CommonJS) and are picked up automatically through the exports map. The StylesheetLoader and OutputSettings types are exported as well.

Serializing output (xsl:output)

transformToString(source) serializes the result tree according to the xsl:output element of the stylesheet (XSLT 1.0 section 16). Unlike the DOM based methods it returns ready to write markup, so the CLI and Node.js users do not need a separate XMLSerializer or a hand rolled re-indenter.

const xslt = parser.parseFromString(`<?xml version="1.0"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/"><BAR><QUX/></BAR></xsl:template>
  </xsl:stylesheet>`, 'application/xml');

const processor = new XSLTProcessor();
processor.importStylesheet(xslt);

processor.transformToString(xmlDoc);
// <?xml version="1.0" encoding="UTF-8"?>
// <BAR>
//   <QUX/>
// </BAR>

Supported xsl:output attributes:

AttributeBehavior
method="xml"XML declaration, minimal escaping, empty elements as <x/> (default). Empty elements in the XHTML namespace follow the XHTML compatibility rules below
method="html"No XML declaration, void elements as <br>, minimized boolean attributes, unescaped script/style
method="xhtml"XML rules, but void elements are written as <br /> and other empty elements get an end tag (<script src="a.js"></script>, <div></div>), so the output also parses as HTML. Elements in other namespaces keep <x/>
method="text"Concatenation of all text nodes, no escaping
indent="yes"Newline plus two-space indentation for element-only content; mixed content and pre/script/style/textarea are left untouched
encoding, version, standaloneWritten into the XML declaration
omit-xml-declaration="yes"Suppresses the XML declaration
doctype-public, doctype-systemEmit a <!DOCTYPE ...> before the document element
cdata-section-elementsText children of the listed elements are wrapped in <![CDATA[...]]>, split around any ]]>
media-typeParsed and exposed on the settings object

disable-output-escaping="yes" on xsl:text and xsl:value-of is honored: the generated text is emitted verbatim, so &lt;b&gt; reaches the output as <b>.

The serializer can also be used on its own, for example on a fragment produced by transformToFragment:

import { serializeResult } from '@tradik/xslt-processor';

serializeResult(fragment, { method: 'html', indent: 'yes' });

When method is absent (or auto), the output method is derived from the result tree: html when the document element is html in no namespace, xml otherwise.

Parameters Example

const processor = new XSLTProcessor();
processor.importStylesheet(xsltDoc);

// Set parameters
processor.setParameter(null, 'sortOrder', 'ascending');
processor.setParameter(null, 'itemsPerPage', 10);

// Get parameter
const sortOrder = processor.getParameter(null, 'sortOrder');

// Clear parameters
processor.clearParameters();

Utility Functions

import {
  isNativeXSLTSupported,
  installGlobal,
  serializeResult,
  markRawText
} from '@tradik/xslt-processor';

// Check if native XSLT is functional
if (!isNativeXSLTSupported()) {
  console.log('Using JS implementation');
}

// Install as global XSLTProcessor
installGlobal(); // Only if native not available
installGlobal(true); // Force install

// Serialize any result tree with xsl:output settings
serializeResult(node, { method: 'xml', indent: 'yes' });

// Mark a text node so that it is emitted without escaping
markRawText(document.createTextNode('<b>raw</b>'));

XsltEngine options

new XsltEngine({ maxResultSize, maxRecursionDepth }) chooses the XPath limits inside a transformation, see DoS Prevention Limits.

Other XsltEngine options: stylesheetLoader, documentLoader (see Loaders) and domParser, a DOMParser-compatible object used to parse XML strings returned by loaders. It defaults to the global DOMParser or the stylesheet document's window, so it only needs to be set for DOM implementations such as @xmldom/xmldom in Node.js. setStylesheetLoader() and setDocumentLoader() return the engine, so calls can be chained.

Asynchronous and streaming API

Non-W3C additions for loading stylesheets over the network and producing large results incrementally. The synchronous W3C methods are unchanged.

MethodDescription
importStylesheetAsync(style, stylesheetUri?, { loader?, documentLoader?, signal? })Loads the xsl:import/xsl:include tree (in parallel, each URI once) and the literal document('...') URIs with fetch or a custom loader, then compiles synchronously. style may be a Node, a string, bytes, a ReadableStream or an async iterable
transformAsync(source, { signal?, stylesheet?, stylesheetUri?, fetchStylesheet?, fetchDocument? })Returns a Promise<string> with the serialized result; failures reject. Sources may be nodes, strings, bytes, ReadableStreams or async iterables, decoded by byte order mark, then the XML declaration's encoding, then UTF-8
transformToStream(source, { signal?, chunkSize? })Returns a ReadableStream<string> serialized on demand in chunks of about 16 KiB, with backpressure and cancellation
// Browser: fetch the stylesheet and everything it imports, then transform
const processor = new XSLTProcessor();
const url = new URL('/xsl/main.xsl', location.href).href;
await processor.importStylesheetAsync((await fetch(url)).body, url);
const html = await processor.transformAsync((await fetch('/data.xml')).body);

// Node.js: pipe a large result without building one big string
import { Readable } from 'node:stream';
Readable.fromWeb(processor.transformToStream(xmlDoc, { signal })).pipe(process.stdout);

Limits: XSLT 1.0 needs random access to the whole source and result trees, so inputs are read fully before parsing and the result tree is built in memory. Streaming bounds the output text and delivers the first bytes before serialization ends. The transformation itself is synchronous and cannot be aborted midway; the signal is honoured while loading and reading, and between output chunks. Only literal document('...') URIs are preloaded; computed ones use setDocumentLoader. Constant-memory input streaming would need XSLT 3.0 streamability.

The building blocks are exported as well: serializeChunks(node, settings?, { chunkSize? }), DEFAULT_CHUNK_SIZE, and the engine-level transformToChunks(engine, node, options) and transformToStream(engine, node, options).

maxTemplateDepth (default 3000, exported as XSLT_MAX_TEMPLATE_DEPTH) limits the nesting of template instantiations, like libxslt's xsltMaxDepth: new XSLTProcessor({ maxTemplateDepth: 10000 }).

DOM implementations in Node.js

Featurejsdom@xmldom/xmldom 0.9+
importStylesheet, transformToString, async and streaming APIyesyes
transformToDocument, xml and text outputyesyes
transformToDocument, html outputHTML document with HTMLElementsxmldom HTML document (no body/head accessors)
transformToFragment into an XML documentyesyes
transformToFragment into an HTML document (real HTMLElements, like Chrome)yesno HTML documents
Entities from the internal DTD subsetexpandednot expanded

With xmldom, set globalThis.DOMParser = DOMParser (or pass domParser to XsltEngine) so string results of loaders can be parsed, and create owner documents with new DOMImplementation().createDocument(null, null). linkedom (no XML namespace support) and xmldom 0.8 are not supported.

This page is generated from docs/API.md in the repository. Corrections are welcome as a pull request to that file.