xslt 1.6.2

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global xslt --version 1.6.2
                    
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.2
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=xslt&version=1.6.2
                    
nuke :add-package xslt --version 1.6.2
                    

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.4 59 8/16/2026
1.6.3 60 8/14/2026
1.6.2 53 8/13/2026
1.6.1 70 8/4/2026
1.6.0 72 7/31/2026
1.5.0 73 7/27/2026
1.4.25 75 7/17/2026
1.4.24 70 7/14/2026
1.4.23 88 7/12/2026
1.4.22 82 7/10/2026
1.4.21 74 7/9/2026
1.4.20 64 7/9/2026
1.4.19 77 7/9/2026
1.4.18 70 7/8/2026
1.4.17 76 7/7/2026
1.4.16 82 6/30/2026
1.4.15 84 6/25/2026
1.4.14 90 6/22/2026
1.4.13 86 6/21/2026
1.4.12 85 6/19/2026
Loading failed

### Fixes

- **An `xsl:attribute` (or `xsl:namespace`) inside a typed `xsl:variable` / `xsl:param` / `xsl:with-param` body no longer raises a spurious `XTDE0420` when the construction happens inside a temporary tree.** An `as=`-typed sequence-constructor body builds a *sequence*, not a temporary tree (XSLT 3.0 §9.3) — no document node wraps it, so attribute and namespace nodes are legal members of the result. The engine left the document-construction depth at whatever the enclosing scope had, so `<xsl:attribute>` inside `<xsl:variable as="attribute()*">` looked like an attempt to attach an attribute to a document node and failed with `XTDE0420: Cannot add an attribute node to a document node`. The typed variable, param, with-param, and param-default-body seams now neutralize that depth for the body and restore it afterwards, matching what the user-function seam already did. `as="document-node()"` is deliberately excluded — that body really is wrapped in a document node. Reported by Martin Honnen against DocBook xslTNG 2.8.0 and 2.8.3 (`modules/attributes.xsl:421`), where the `<xsl:variable name="attr" as="attribute()*"><xsl:apply-templates select="@*"/></xsl:variable>` idiom appears roughly twenty times; the whole document transform failed on the sample article. Regression since the DocBook support landed in the 1.4.x–1.5.x line.

- **An `xsl:namespace` that re-declares a binding the element already has is now a no-op instead of emitting a duplicate declaration.** Adding a namespace node for a (prefix, URI) the element under construction already carries is not an error — `XTDE0430` covers only the case where the URIs *differ* — but the engine emitted both, producing two identical `xmlns:p` attributes on one start tag and output that is not well-formed XML. A conflicting URI still raises `XTDE0430`, and a redundant re-declaration of a binding an ancestor already provides is now omitted (same infoset, one fewer declaration). Found while generating DocBook xslTNG's `param.xsl` with our own engine: `tools/generate-parameters.xsl` uses `xsl:namespace-alias` to put the result root in the XSL namespace and then re-declares that same binding with `<xsl:namespace name="xsl">`, so the generated stylesheet could not be reparsed.

### Testing

- Both fixes carry regression tests (`MartinDocBookTypedAttributeVariableTests`, `NamespaceDuplicateDeclarationTests`) covering the reported shapes, the guard cases that must keep failing, and the `as="document-node()"` exclusion. Neither bug was reachable by the existing suites: the unit suite was green at 1196 and the W3C conformance suite asserts only that some tests passed, so it cannot fail on a regression. A repro harness that runs the engine against the real DocBook xslTNG stylesheets now ships in `.claude/skills/engine-repro/`; it builds a runnable xslTNG tree from a source checkout using the engine itself, with no Java, Gradle, or network dependency.