JavaScript implementation of XSLTProcessor for browser environments and CLI
npm install @tradik/xslt-processor





JavaScript implementation of XSLTProcessor for browser environments and Node.js CLI. This package provides a complete implementation of the W3C XSLTProcessor API that can be used as a drop-in replacement for the native browser implementation.
Chrome and other browsers are deprecating native XSLTProcessor support:
- Chrome 143+: XSLTProcessor starts showing deprecation warnings
- Chrome 164 (August 2027): Full removal of native XSLT support
This library ensures your XSLT-based applications continue to work regardless of browser support.
- 1:1 Native API Compatibility: Drop-in replacement for native XSLTProcessor
- Full XSLT 1.0 Support: Implements the complete W3C XSLT 1.0 specification
- XPath 1.0 Engine: Built-in XPath evaluator with all core functions
- Zero Dependencies: Standalone implementation with no external dependencies
- Multiple Formats: ESM, CommonJS, and browser IIFE bundles
- TypeScript Support: Includes TypeScript declarations
- WCAG 2.2 Compliant: Designed with accessibility in mind
``bash`
npm install @tradik/xslt-processor
Use a CDN for the easiest browser integration - no build step required:
`html
`
CDN URLs:
| CDN | URL |
|-----|-----|
| jsDelivr | https://cdn.jsdelivr.net/npm/@tradik/xslt-processor@1/dist/xslt-processor.browser.min.js |https://unpkg.com/@tradik/xslt-processor@1/dist/xslt-processor.browser.min.js
| unpkg | |
> Tip: Use @1 for latest 1.x version, or @1.0.0 for exact version pinning.
If you prefer local installation:
`html`
`javascript
import { XSLTProcessor, installGlobal } from '@tradik/xslt-processor';
// Optional: Force install as global XSLTProcessor
installGlobal();
// Or use directly
const processor = new XSLTProcessor();
const parser = new DOMParser();
// Load and parse XSLT stylesheet
const xsltText = await fetch('template.xsl').then(r => r.text());
const xsltDoc = parser.parseFromString(xsltText, 'application/xml');
processor.importStylesheet(xsltDoc);
// Load and parse XML source
const xmlText = await fetch('data.xml').then(r => r.text());
const xmlDoc = parser.parseFromString(xmlText, 'application/xml');
// Transform
const fragment = processor.transformToFragment(xmlDoc, document);
document.getElementById('output').appendChild(fragment);
`
`javascript
const { XSLTProcessor } = require('@tradik/xslt-processor');
const processor = new XSLTProcessor();
// ...
`
The package includes a command-line tool for transforming XML documents:
`bashGlobal installation
npm install -g @tradik/xslt-processor
#### CLI Options
| Option | Description |
|--------|-------------|
|
-o, --output | Write output to file instead of stdout |
| -p, --param | Set XSLT parameter (can be used multiple times) |
| -f, --format | Format output with indentation |
| -h, --help | Show help message |
| -v, --version | Show version number |API Reference
$3
#### Constructor
`javascript
const processor = new XSLTProcessor();
`#### Methods
| Method | Description |
|--------|-------------|
|
importStylesheet(node) | Imports an XSLT stylesheet from a Document or Element node |
| transformToFragment(source, output) | Transforms XML and returns a DocumentFragment |
| transformToDocument(source) | Transforms XML and returns an XMLDocument |
| setParameter(namespaceURI, localName, value) | Sets an XSLT parameter |
| getParameter(namespaceURI, localName) | Gets an XSLT parameter value |
| removeParameter(namespaceURI, localName) | Removes an XSLT parameter |
| clearParameters() | Removes all parameters |
| reset() | Resets the processor, removing stylesheet and parameters |$3
`javascript
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();
`$3
To use
xsl:import and xsl:include elements in your stylesheets, you need to configure a stylesheet loader that tells the processor how to fetch external stylesheets:`javascript
import { XSLTProcessor } from '@tradik/xslt-processor';const processor = new XSLTProcessor();
// Configure stylesheet loader
processor.engine.setStylesheetLoader((href, baseUri) => {
// href: the href attribute from xsl:import/xsl:include
// baseUri: the URI of the importing stylesheet
// Option 1: Return a parsed Document
const response = await fetch(href);
const text = await response.text();
const parser = new DOMParser();
return parser.parseFromString(text, 'application/xml');
// Option 2: Return XML string (will be parsed automatically)
return await fetch(href).then(r => r.text());
});
// Now xsl:import and xsl:include will work
processor.importStylesheet(mainStylesheet, '/styles/main.xsl');
`#### Import vs Include Behavior
- xsl:include: Merges templates at the same precedence level. If multiple templates match, priority attribute decides.
- xsl:import: Imported templates have lower precedence than importing stylesheet. The importing stylesheet's templates always win over imported ones with the same match pattern.
`xml
`$3
`javascript
import { isNativeXSLTSupported, installGlobal } 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
`Complete Example
Here's a full example transforming a list of products into an HTML table:
products.xml:
`xml
Widget
29.99
150
Gadget
49.99
75
`products.xsl:
`xml
ID Name Price Stock
$
In Stock
Low Stock
Out of Stock
`JavaScript:
`javascript
import { XSLTProcessor } from '@tradik/xslt-processor';const processor = new XSLTProcessor();
processor.importStylesheet(xsltDoc);
processor.setParameter(null, 'title', 'My Product List');
const result = processor.transformToFragment(xmlDoc, document);
document.body.appendChild(result);
`CLI:
`bash
xslt products.xml products.xsl -p title="My Product List" -f -o catalog.html
`Security Features
The XPath evaluator includes comprehensive security hardening to prevent common attack vectors.
$3
| Limit | Default | Description |
|-------|---------|-------------|
|
MAX_RECURSION_DEPTH | 100 | Prevents stack overflow from deeply nested expressions |
| MAX_RESULT_SIZE | 10,000 | Prevents memory exhaustion from large result sets |
| MAX_STRING_LENGTH | 1,000,000 | Limits string processing to prevent memory issues |$3
The following variable names are blocked:
-
__proto__, constructor, prototype
- __defineGetter__, __defineSetter__
- __lookupGetter__, __lookupSetter__$3
- AST Validation: All AST nodes are validated before evaluation
- Type Safety: Strict type checking on all inputs
- Safe Variable Lookup: Uses
hasOwnProperty to prevent prototype chain attacks$3
`javascript
import { XPathEvaluator, XPathContext, parse } from '@tradik/xslt-processor';const evaluator = new XPathEvaluator({
maxRecursionDepth: 50, // Lower for untrusted input
maxResultSize: 1000, // Limit result set size
maxStringLength: 10000 // Limit string operations
});
const ast = parse('//item');
const context = new XPathContext(xmlDoc);
const result = evaluator.evaluate(ast, context);
`XSLT Elements Supported
| Element | Status |
|---------|--------|
|
xsl:apply-templates | Supported |
| xsl:attribute | Supported |
| xsl:call-template | Supported |
| xsl:choose / when / otherwise | Supported |
| xsl:comment | Supported |
| xsl:copy | Supported |
| xsl:copy-of | Supported |
| xsl:element | Supported |
| xsl:for-each | Supported |
| xsl:if | Supported |
| xsl:message | Supported |
| xsl:number | Supported |
| xsl:output | Supported |
| xsl:param | Supported |
| xsl:processing-instruction | Supported |
| xsl:sort | Supported |
| xsl:template | Supported |
| xsl:text | Supported |
| xsl:value-of | Supported |
| xsl:variable | Supported |
| xsl:with-param | Supported |
| xsl:import | Supported |
| xsl:include | Supported |XPath Functions Supported
$3
- count(), id(), last(), local-name(), name(), namespace-uri(), position()$3
- concat(), contains(), normalize-space(), starts-with(), string(), string-length(), substring(), substring-after(), substring-before(), translate()$3
- boolean(), false(), lang(), not(), true()$3
- ceiling(), floor(), number(), round(), sum()Development
$3
- Node.js 25+ (for native test runner)
- Docker (optional, for containerized testing)
$3
`bash
cd services/xslt-processor
npm install
`$3
`bash
Run tests
npm testRun tests with watch mode
npm run test:watchBuild bundles
npm run buildLint code
npm run lintFormat code
npm run format
`$3
`bash
Run tests in container
docker-compose run testDevelopment with hot reload
docker-compose run devBuild bundles
docker-compose run build
`$3
The package is automatically published to npm when a GitHub release is created or a version tag is pushed.
Prerequisites:
1. Set up
NPM_TOKEN secret in GitHub repository settings
2. Ensure version in package.json matches the release tagRelease Process:
`bash
1. Update version in package.json
npm version patch # or minor, major2. Push the tag
git push origin --tags3. Create a GitHub release (or push triggers automatically)
`Automated Workflow:
1. Runs all tests and linting checks
2. Performs security audit with
npm audit
3. Builds distribution bundles
4. Publishes to npm with provenance (supply chain security)
5. Uploads build artifacts to GitHubBrowser Compatibility
This library provides a JavaScript polyfill for XSLTProcessor that works across all modern browsers.
$3
| Browser | Minimum Version | ES Modules | Status |
|---------|-----------------|------------|--------|
| Chrome | 90+ | Yes | Fully Supported |
| Firefox | 88+ | Yes | Fully Supported |
| Safari | 14+ | Yes | Fully Supported |
| Edge | 90+ | Yes | Fully Supported |
| Opera | 76+ | Yes | Fully Supported |
| Samsung Internet | 15+ | Yes | Fully Supported |
| Node.js | 25+ | Yes | Fully Supported |
$3
| Browser | Deprecation Warning | Full Removal |
|---------|---------------------|--------------|
| Chrome | v143 (2026) | v164 (August 2027) |
| Edge | v143 (2026) | v164 (August 2027) |
| Other Chromium | v143 (2026) | v164 (August 2027) |
$3
`javascript
import { isNativeXSLTSupported, installGlobal } from '@tradik/xslt-processor';// Check native support and auto-install polyfill
if (!isNativeXSLTSupported()) {
installGlobal();
console.log('Using JavaScript XSLT polyfill');
}
`W3C Standards Compliance
This implementation follows these W3C specifications with comprehensive test coverage to ensure compliance.
$3
| Specification | Version | Status |
|---------------|---------|--------|
| XPath 1.0 | W3C Recommendation, 16 November 1999 | Full Compliance |
| XSLT 1.0 | W3C Recommendation, 16 November 1999 | Full Compliance |
| DOM Level 3 Core | W3C Recommendation, 7 April 2004 | Full Compliance |
$3
| Section | Feature | Status | Notes |
|---------|---------|--------|-------|
| 2 | Stylesheet Structure | Supported |
xsl:stylesheet, xsl:transform elements |
| 3 | Data Model | Supported | Seven node types per XPath data model |
| 5 | Template Rules | Supported | Pattern matching, priority calculation |
| 5.1 | Processing Model | Supported | Built-in templates for all node types |
| 5.2 | Patterns | Supported | All pattern syntax including predicates |
| 5.3 | Defining Template Rules | Supported | match, name, priority, mode attributes |
| 5.4 | Applying Template Rules | Supported | xsl:apply-templates with select, mode |
| 5.5 | Conflict Resolution | Supported | Import precedence and priority ordering |
| 6 | Named Templates | Supported | xsl:call-template, xsl:with-param |
| 7 | Creating Result Tree | Supported | Literal result elements, attribute value templates |
| 7.1.2 | Creating Elements | Supported | xsl:element with dynamic names/namespaces |
| 7.1.3 | Creating Attributes | Supported | xsl:attribute with dynamic names/namespaces |
| 7.2 | Creating Text | Supported | xsl:value-of, xsl:text |
| 7.3 | Creating PIs | Supported | xsl:processing-instruction |
| 7.4 | Creating Comments | Supported | xsl:comment |
| 7.5 | Copying | Supported | xsl:copy, xsl:copy-of |
| 7.6 | Attribute Sets | Supported | xsl:attribute-set, use-attribute-sets |
| 7.6.2 | Namespace Aliases | Supported | xsl:namespace-alias |
| 8 | Repetition | Supported | xsl:for-each |
| 9 | Conditional Processing | Supported | xsl:if, xsl:choose, xsl:when, xsl:otherwise |
| 10 | Sorting | Supported | xsl:sort with multiple keys, data-types, order |
| 11 | Variables/Parameters | Supported | xsl:variable, xsl:param, scoping rules |
| 11.1 | Result Tree Fragments | Supported | RTF handling as per spec |
| 12 | Additional Functions | Supported | document(), key(), format-number(), current(), generate-id(), system-property() |
| 12.3 | Number Formatting | Supported | xsl:number with all formatting options |
| 13 | Messages | Supported | xsl:message with terminate attribute |
| 14 | Extensions | Partial | xsl:fallback supported |
| 15 | Fallback | Supported | xsl:fallback element |
| 16 | Output | Supported | xsl:output with method, encoding, indent |$3
| Section | Feature | Status | Notes |
|---------|---------|--------|-------|
| 2.1 | Location Steps | Supported | axis::node-test[predicate] |
| 2.2 | Axes | Supported | All 13 axes implemented |
| 2.3 | Node Tests | Supported | Name tests,
node(), text(), comment(), processing-instruction() |
| 2.4 | Predicates | Supported | Position and boolean predicates |
| 2.5 | Abbreviated Syntax | Supported | ., .., @, // |
| 3.1 | Basics | Supported | Expression evaluation |
| 3.2 | Function Calls | Supported | All core functions |
| 3.3 | Node-sets | Supported | Union operator \| |
| 3.4 | Booleans | Supported | and, or, not() |
| 3.5 | Numbers | Supported | IEEE 754 double-precision |
| 3.6 | Strings | Supported | Unicode string handling |
| 3.7 | Lexical Structure | Supported | Full tokenization |
| 4.1 | Node Set Functions | Supported | last(), position(), count(), id(), local-name(), namespace-uri(), name() |
| 4.2 | String Functions | Supported | string(), concat(), starts-with(), contains(), substring-before(), substring-after(), substring(), string-length(), normalize-space(), translate() |
| 4.3 | Boolean Functions | Supported | boolean(), not(), true(), false(), lang() |
| 4.4 | Number Functions | Supported | number(), sum(), floor(), ceiling(), round() |$3
| Axis | Status | Description |
|------|--------|-------------|
|
child | Supported | Children of context node |
| descendant | Supported | Descendants of context node |
| parent | Supported | Parent of context node |
| ancestor | Supported | Ancestors of context node |
| following-sibling | Supported | Following siblings |
| preceding-sibling | Supported | Preceding siblings |
| following | Supported | Nodes after context in document order |
| preceding | Supported | Nodes before context in document order |
| attribute | Supported | Attributes of context node |
| namespace | Supported | Namespace nodes |
| self | Supported | Context node itself |
| descendant-or-self | Supported | Context node and descendants |
| ancestor-or-self | Supported | Context node and ancestors |$3
| Interface | Status | Notes |
|-----------|--------|-------|
|
Node | Supported | All node type constants |
| Document | Supported | createElement, createTextNode, createComment, etc. |
| Element | Supported | getAttribute, setAttribute, namespace methods |
| Attr | Supported | Attribute nodes with namespace support |
| Text | Supported | Text node handling |
| Comment | Supported | Comment nodes |
| ProcessingInstruction | Supported | PI nodes with target and data |
| DocumentFragment | Supported | Fragment handling in transforms |
| NamedNodeMap | Supported | Attribute collections |
| NodeList | Supported | Child node collections |$3
This implementation provides full compatibility with the MDN XSLTProcessor API:
| Method | Status | Notes |
|--------|--------|-------|
|
importStylesheet(node) | Supported | Accepts Document or Element |
| transformToFragment(source, output) | Supported | Returns DocumentFragment |
| transformToDocument(source) | Supported | Returns XMLDocument |
| setParameter(namespaceURI, localName, value) | Supported | Full namespace support |
| getParameter(namespaceURI, localName) | Supported | Returns parameter value |
| removeParameter(namespaceURI, localName) | Supported | Removes single parameter |
| clearParameters() | Supported | Removes all parameters |
| reset() | Supported | Resets processor state |$3
| Specification | Tests | Coverage |
|---------------|-------|----------|
| XSLT 1.0 Elements | 82+ | 100% of supported elements |
| XPath 1.0 Functions | 50+ | 100% of core functions |
| XPath 1.0 Axes | 26+ | All 13 axes |
| DOM Level 3 | 20+ | Core interfaces |
| XSLTProcessor API | 39+ | All methods |
| Security | 34+ | DoS prevention, prototype pollution |
| Total | 441 | 99.41% line coverage |
Style Guide
$3
| Usage | Color | Hex |
|-------|-------|-----|
| Primary | Blue |
#2563eb |
| Success | Green | #16a34a |
| Warning | Amber | #d97706 |
| Error | Red | #dc2626 |
| Text | Gray | #1f2937 |
| Background | White | #ffffff` |All colors meet WCAG 2.2 AA contrast requirements for accessibility.
BSD-3-Clause License - see LICENSE.md for details.
- MDN XSLTProcessor
- libxslt - Reference implementation in C