Posts

Chrome is removing XSLT on November 17, 2026: what breaks and what to do

14 Aug 2026

Chrome 158 drops native XSLT — XSLTProcessor and xml-stylesheet stop working. Who is actually affected, honest pros and cons of the WASM polyfill vs server-side migration paths, and how to test your stylesheets outside the browser today.

Quick answer: Chrome removes built-in XSLT support in version 158, shipping November 17, 2026, with deprecation warnings already appearing since Chrome 142–143 (official announcement). Both the XSLTProcessor JavaScript API and <?xml-stylesheet?> processing instructions stop working. Firefox and WebKit have signalled they will follow. Your migration options are a WASM polyfill, server-side transformation, or build-time precompilation — and you can verify today whether your stylesheets run correctly outside the browser.

What exactly is being removed

Two things, both part of the same removal:

  1. XSLTProcessor — the JavaScript API (importStylesheet(), transformToFragment(), transformToDocument()). Any client-side code calling it throws once the API is gone.
  2. <?xml-stylesheet type="text/xsl" ...?> — the processing instruction that made the browser auto-render an XML document (RSS feeds, sitemaps, DocBook-ish documentation, legacy intranet reports) through a stylesheet. Those URLs will render as raw XML.

Why, and why now

Chrome’s stated numbers: XSLT appears in roughly 0.02% of page loads, and the xml-stylesheet processing instruction in under 0.001%. The driving reason is security, not usage: browsers ship XSLT via libxslt, a minimally-maintained C library with a history of memory-safety vulnerabilities — CVE-2025-7425 (use-after-free) and CVE-2022-22834 among them. Maintaining an interpreter for a 1999-era spec in the browser’s most attacked process stopped being worth it. Since Firefox and WebKit have indicated the same direction, “wait for another browser” is not a plan.

Worth remembering: the browsers only ever implemented XSLT 1.0. Nothing about 2.0/3.0 changes here, because it was never in the browser to begin with.

Who is actually affected

  • Sites rendering XML directly with xml-stylesheet — styled RSS/Atom feeds, sitemap.xml viewers, legacy documentation systems. This is the biggest visible breakage.
  • Web apps calling XSLTProcessor — often deep inside old admin panels and enterprise frontends that nobody has touched in years. grep -r XSLTProcessor your codebase.
  • Not affected: anything doing XSLT server-side (Java/Saxon, .NET, PHP, integration middleware). That is where most production XSLT already lives.

Your options, honestly

OptionProsCons
WASM polyfill (libxslt compiled to WebAssembly, what Chrome recommends for drop-in continuity)Minimal code change; keeps rendering client-side; works for XSLTProcessor call sitesAdds a non-trivial WASM payload to first load; you now ship and patch libxslt yourself — the same library the browsers dropped for security reasons; PI-based auto-rendering needs extra glue
Server-side transformationReal processor (Saxon opens up XSLT 2.0/3.0); output is plain HTML so nothing depends on browser support ever again; testable in CINeeds a backend or edge function; XML URLs must be routed/proxied through it
Precompile at build timeZero runtime cost; ideal when the XML is static (docs, feeds with static templates)Only works for content known at build time; dynamic XML still needs one of the above

Our take: the polyfill is a reasonable bridge for a large XSLTProcessor codebase you cannot rework before November. As a destination, server-side or build-time wins — you swap a deprecated browser dependency for a supported processor instead of vendoring the deprecated one.

Test your stylesheets outside the browser — today

Before choosing, find out whether your stylesheets even behave the same outside the browser. Paste one into XSLT Playground together with a sample XML input and run it with version = 1.0. That executes a JAXP (Xalan-class) XSLT 1.0 processor — same spec level and very close semantics to what the browser did, so differences surface immediately (typical ones: reliance on browser-specific output quirks, document() calls resolving against URLs, disable-output-escaping).

Here is a browser-typical stylesheet — XML rendered as an HTML table — run exactly that way:

Input XML:

<catalog>
  <book>
    <title>XSLT Cookbook</title>
    <price>39.95</price>
  </book>
  <book>
    <title>XPath Essentials</title>
    <price>24.50</price>
  </book>
</catalog>

Stylesheet (run with version 1.0):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/catalog">
    <table>
      <tr><th>Title</th><th>Price</th></tr>
      <xsl:for-each select="book">
        <tr>
          <td><xsl:value-of select="title"/></td>
          <td><xsl:value-of select="price"/></td>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

Output (exactly as returned):

<table>
    <tr>
        <th>Title</th><th>Price</th>
    </tr>
    <tr>
        <td>XSLT Cookbook</td><td>39.95</td>
    </tr>
    <tr>
        <td>XPath Essentials</td><td>24.50</td>
    </tr>
</table>

If it runs clean at 1.0, your server-side migration is low-risk — and once you are server-side you can optionally move to 2.0/3.0 and simplify the stylesheet (grouping, regex, sequences). If it errors, the Saxon error triage guide maps each code to its fix.

The browser removal lands the same year the venerable FreeFormatter site shut down — client-side and ad-supported XSLT are both winding down, while server-side XSLT keeps running payment migrations (ISO 20022) and e-invoicing validation (Peppol/EN 16931) at scale. XSLT is not dying; it is relocating.

Test your stylesheets now: xsltplayground.com.