← Deprecate and remove XSLT

v152 · removal · javascript api

XSLTProcessor

Baseline widely available — being removed

  • Chrome · 1, removal from 158
  • Edge · 12, follows Chromium
  • Firefox · 1, removal planned
  • Safari · 3.1, removal planned

Support versions per BCD api.XSLTProcessor; removal plan per the developer.chrome.com removal guide. See the timeline. ChromeStatus: 4709671889534976 — Deprecate and remove XSLT.

XSLTProcessor is the JavaScript API for running XSLT 1.0 transformations in the page: load a stylesheet with importStylesheet(), then transform XML with transformToFragment() or transformToDocument(), with setParameter()/getParameter()/removeParameter()/clearParameters()/reset() managing stylesheet parameters and reuse. The entire interface is deprecated since Chrome 143 and removed from Stable in Chrome 158 (Nov 17, 2026); when the XSLT runtime feature is disabled, window.XSLTProcessor is simply gone.

Removed API — do not write new code against this

This page exists so you can recognize, detect, and migrate existing usage. New code should use SaxonJS (XSLT 3.0 in JS), server-side transformation, or JSON+JS rendering. Existing code can be kept alive with the WASM polyfill (a drop-in XSLTProcessor replacement) or, temporarily, the “XSLT” deprecation origin trial / XSLTEnabled policy (until Chrome 176).

syntax

The WHATWG DOM Standard's §9.1 Interface XSLTProcessor (verbatim):

[Exposed=Window]
interface XSLTProcessor {
  constructor();
  undefined importStylesheet(Node style);
  [CEReactions] DocumentFragment transformToFragment(Node source, Document output);
  [CEReactions] Document transformToDocument(Node source);
  undefined setParameter([LegacyNullToEmptyString] DOMString namespaceURI, DOMString localName, any value);
  any getParameter([LegacyNullToEmptyString] DOMString namespaceURI, DOMString localName);
  undefined removeParameter([LegacyNullToEmptyString] DOMString namespaceURI, DOMString localName);
  undefined clearParameters();
  undefined reset();
};

What Chrome actually ships (xslt_processor.idl, verbatim — note the differences that matter for migration):

[ Exposed=Window, RuntimeEnabled=XSLT ] interface XSLTProcessor {
    [RaisesException, CallWith=Document] constructor();
    undefined importStylesheet(Node style);
    // TODO(foolip): In Gecko, the transformTo*() methods throw an exception in
    // case of error instead of returning null.
    DocumentFragment? transformToFragment(Node source, Document output);
    Document? transformToDocument(Node source);
    undefined setParameter(DOMString? namespaceURI, DOMString localName, DOMString value);
    DOMString? getParameter(DOMString? namespaceURI, DOMString localName);
    undefined removeParameter(DOMString? namespaceURI, DOMString localName);
    undefined clearParameters();
    undefined reset();
};

Key divergences between the spec text and the shipping implementation:

Source: WHATWG DOM §9.1; Chromium xslt_processor.idl (both fetched 2026-07-29).

members and behavior when removed

MemberBehavior todayAfter removal
new XSLTProcessor()Constructs a processor; can throw in Chromium ([RaisesException])ReferenceError/TypeError — the global no longer exists
importStylesheet(style: Node)Loads/compiles an XSLT 1.0 stylesheet node for later transformsUnreachable (no global)
transformToFragment(source: Node, output: Document)Transforms source, returns a DocumentFragment owned by output; null on error in Chromium, throws in GeckoUnreachable — polyfill implements the same contract
transformToDocument(source: Node)Transforms source into a new Document; nullable in ChromiumUnreachable — polyfill implements the same contract
setParameter(ns, name, value) / getParameter(ns, name) / removeParameter(ns, name)Manage stylesheet parameters (Chromium: string values, nullable namespace)Unreachable — polyfill implements parameter management
clearParameters()Drops all set parametersUnreachable
reset()Resets the processor to its initial state (stylesheet and parameters cleared)Unreachable

All methods are synchronous — including network-adjacent work: native XSLT loads xsl:include/xsl:import/document() resources synchronously and can do so cross-origin. That combination is precisely what the polyfill cannot fully reproduce (its fetches go through the CORS-checked async fetch()), which is the main behavioral cliff for migrated code.

Source: Chromium IDL + TODO comments; polyfill README (limitations); MDN XSLTProcessor (member semantics).

feature detection

Because the interface is [RuntimeEnabled=XSLT]-gated, detection is a simple existence check — and it is exactly what the surveyed sites that keep working with XSLT disabled already do (roughly 72% of ~220 surveyed sites):

const hasNativeXSLT = typeof XSLTProcessor !== "undefined";

if (!hasNativeXSLT) {
  // Chrome with XSLT disabled (pre-stable now, Stable from 158).
  // Fall back to SaxonJS or the WASM polyfill.
}

To test the removed world before it ships: toggle chrome://flags/#xslt to Disabled (flag wired to blink::features::kXSLT in about_flags.cc) or launch with --disable-blink-features=XSLT.

Source: xslt_processor.idl (RuntimeEnabled gating); about_flags.cc; removal guide.

migration: the polyfill and SaxonJS

The XSLT polyfill (npm: xslt-polyfill) is a WebAssembly build of the same libxslt+libxml2 engine, exposing a full XSLTProcessor replacement — importStylesheet, transformToDocument, transformToFragment, and parameter management — so existing call sites keep working:

<script src="xslt-polyfill.min.js"></script>
<script>
const xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsltDoc);
const fragment = xsltProcessor.transformToFragment(xmlDoc, document);
</script>

Documented limitations (from the polyfill README):

SaxonJS is the maintained, full-fidelity path: XSLT 3.0 (and eventually 4.0) implemented in JavaScript — strictly more capable than the browser feature being removed, at the cost of a library dependency and a different API.

Source: xslt_polyfill README (usage, implementation, limitations); removal guide (client-side XSLT in JavaScript).

error behavior

SituationChromium (shipping)Gecko (per Chromium IDL comment)
Transformation fails inside transformToFragment/transformToDocumentReturns nullThrows an exception
Constructor failureCan throw ([RaisesException])
Using the API after the feature is disabledXSLTProcessor is undefined — accessing it is a ReferenceError in sloppy-scope lookups; calling new XSLTProcessor() fails before any XSLT runs
Source: Chromium xslt_processor.idl (nullable returns, TODO comment).

lifecycle and deprecation mechanics

  1. Chrome 143+: constructing/using the API logs a deprecation warning (console + Lighthouse); a deprecation report with id "XSLT" is emitted.
  2. Pre-stable channels (Canary/Dev/Beta): the XSLT runtime feature is Finch-disabled by default as an early warning; XSLTSpecialTrial switches the console message to a “special trial run” variant.
  3. Chrome 158: Stable disables the feature; the interface disappears unless the origin serves a deprecation-trial token or the XSLTEnabled policy is set.
  4. Chrome 176: trial and policy stop working; the API is gone for everyone.
Source: removal guide (timeline); runtime_enabled_features.json5 (XSLT, XSLTSpecialTrial).

browser compatibility

BrowserSupported since (BCD)Removal plan
Chrome1Deprecated 143; disabled pre-stable; Stable removal 158; trial/policy until 176
Edge12Follows Chromium
Firefox1Removal planned (Gecko supportive); no dated plan on the record
Safari3.1Removal planned (WebKit cautiously supportive)

BCD (api/XSLTProcessor.json) records standard_track: true and does not yet record the deprecation — treat the deprecation columns as interim data from the ChromeStatus record until BCD catches up.

Source: BCD + ChromeStatus as linked, fetched 2026-07-29.

security and privacy

Source: removal guide (security rationale); polyfill README.