xslt 1.6.9

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global xslt --version 1.6.9
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local xslt --version 1.6.9
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=xslt&version=1.6.9
                    
nuke :add-package xslt --version 1.6.9
                    

xslt

Command-line XSLT 3.0/4.0 processor for .NET. Transform XML documents from the terminal using the PhoenixmlDb XSLT engine.

Installation

dotnet tool install -g xslt

Usage

# Transform XML with a stylesheet
xslt stylesheet.xsl input.xml

# Write output to a file
xslt -o result.html report.xsl data.xml

# Start from a named template (no source needed)
xslt -it main generate.xsl

# Pass parameters
xslt -p year=2026 -p title="Report" style.xsl data.xml

# Read source from stdin
cat data.xml | xslt transform.xsl

# Show timing breakdown
xslt --timing style.xsl large-input.xml

# Validate a stylesheet without running
xslt --dry-run style.xsl

# Stream large files (lower memory)
xslt --stream style.xsl large-input.xml

Features

  • XSLT 3.0/4.0 — packages, streaming, maps/arrays, higher-order functions, JSON output
  • Multiple output methods — XML, HTML, XHTML, text, JSON, adaptive
  • Streaming — process large files without loading into memory
  • xsl:result-document — generate multiple output files in one transform
  • Parameters — pass values from the command line
  • Timing — built-in performance profiling
  • Tracing — log template matching, function calls, and built-in rules

Documentation

Full documentation at phoenixml.dev

License

Apache-2.0

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.6.10 28 8/27/2026
1.6.9 204 8/26/2026
1.6.8 38 8/26/2026
1.6.7 55 8/24/2026
1.6.6 60 8/23/2026
1.6.5 54 8/22/2026
1.6.4 82 8/16/2026
1.6.3 66 8/14/2026
1.6.2 57 8/13/2026
1.6.1 71 8/4/2026
1.6.0 73 7/31/2026
1.5.0 74 7/27/2026
1.4.25 77 7/17/2026
1.4.24 72 7/14/2026
1.4.23 90 7/12/2026
1.4.22 83 7/10/2026
1.4.21 75 7/9/2026
1.4.20 65 7/9/2026
1.4.19 80 7/9/2026
1.4.18 71 7/8/2026
Loading failed

One engine fix from Martin Honnen's testing, and the error-reporting problems his transcript
exposed alongside it.

### `document-node(element(x:report))` matched nothing

Reported by Martin Honnen: an XSpec report stylesheet fell through to the built-in rule and
died with XTDE0555.

A pattern's name test has its namespace URI resolved to an internal namespace ID by a pass
over the pattern steps. That pass only looked at the step's node test when it *is* a name test
— but a name test also lives one level INSIDE a kind test: `element(x:report)` keeps it in the
kind test's name, `document-node(element(x:report))` in its document-element test. Those kept
their URI with the resolved ID still null, and the matcher ends on

   // This shouldn't happen if namespace resolution is working correctly
   return false;

which is why the template silently matched nothing rather than erroring. So the same name
behaved differently one nesting level apart: `match="x:report"` matched and
`match="element(x:report)"` did not. Martin's report surfaced the `element()` form too, which
nobody had hit.

Verified with negatives as well as positives — wrong namespace, wrong local name, and
unprefixed-means-no-namespace all still correctly reject, because a fix that resolved nothing
and matched everything would pass the positive tests alone.

### The tool reported the error, then crash-dumped over it

Martin's paste showed the shape of it:

   Error: XTDE0555: No matching template found for node in mode with on-no-match='fail'
   Unhandled exception. System.InvalidOperationException: XTDE0555: No matching template …
      [11 stack frames]

exiting 134. The CLI's top-level handler printed a clean error line and then rethrew, so .NET
appended its unhandled-exception report. Every other handler there returns 2, and the XQuery
one says why: "so users don't see a raw .NET stack trace for a spec-defined error".

The rethrow was satisfying an analyzer rule that requires a catch-all to rethrow — wrong for a
command-line tool, where reporting and returning a non-zero exit IS the handling.

   now: XSLT error: XTDE0555: No matching template found …    exit 2

### Every W3C error code is an XsltException

Twelve sites threw spec-defined errors as bare `InvalidOperationException` — XTDE0555,
XPDY0002, XTDE0980, XTTE1000, XTDE0030, XTTE0990, XTTE0510 — carrying no error code, no
stylesheet location, missing the CLI's XSLT handler, and invisible to the accumulator's
deferred-error handling, which keys off the type. All now carry both.

   Xslt.Tests 1301 passed, 0 failed, 1 skipped (1289 at 1.6.8)
   XSLT conformance 10232/10630 = 96.26%, unchanged
   XSpec: the XTDE0555 bucket cleared (5 suites -> 0); those suites now progress further