PhoenixmlDb.Xslt 1.8.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package PhoenixmlDb.Xslt --version 1.8.0
                    
NuGet\Install-Package PhoenixmlDb.Xslt -Version 1.8.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PhoenixmlDb.Xslt" Version="1.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PhoenixmlDb.Xslt" Version="1.8.0" />
                    
Directory.Packages.props
<PackageReference Include="PhoenixmlDb.Xslt" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PhoenixmlDb.Xslt --version 1.8.0
                    
#r "nuget: PhoenixmlDb.Xslt, 1.8.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PhoenixmlDb.Xslt@1.8.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PhoenixmlDb.Xslt&version=1.8.0
                    
Install as a Cake Addin
#tool nuget:?package=PhoenixmlDb.Xslt&version=1.8.0
                    
Install as a Cake Tool

PhoenixmlDb.Xslt

XSLT 4.0 transformation engine for PhoenixmlDb — transform XML documents into HTML, JSON, CSV, text, or other XML formats.

Features

  • XSLT 3.0/4.0 — template matching, streaming, accumulators, packages, maps/arrays
  • All output methods — HTML5, XML, XHTML, JSON, text, CSV, adaptive
  • Multiple outputsxsl:result-document for multi-file generation
  • Full XPath 4.0 — 240+ built-in functions available in all expressions
  • Packages — reusable stylesheet libraries with visibility control

Quick example

using PhoenixmlDb.Xslt;

var transformer = new XsltTransformer();
await transformer.LoadStylesheetAsync(
    File.ReadAllText("style.xsl"),
    new Uri(Path.GetFullPath("style.xsl")));

transformer.SetParameter("title", "My Report");
var html = await transformer.TransformAsync(
    File.ReadAllText("data.xml"));

// Handle secondary outputs (xsl:result-document)
foreach (var (href, content) in transformer.SecondaryResultDocuments)
    File.WriteAllText(Path.Combine(outputDir, href), content);

See the full API overview in the README.

Package Description
PhoenixmlDb.Core Core types and XDM data model (dependency)
PhoenixmlDb.XQuery XQuery 4.0 query engine (dependency)
PhoenixmlDb.Xslt.Cli xslt command-line tool

Documentation

Full documentation at phoenixml.dev

License

Apache 2.0

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 0 9/17/2026
2.0.0 81 9/15/2026
1.8.0 175 9/14/2026
1.7.0 73 9/11/2026
1.6.15 167 9/9/2026
1.6.14 117 9/7/2026
1.6.13 158 9/2/2026
1.6.12 121 8/30/2026
1.6.11 107 8/29/2026
1.6.10 173 8/27/2026
1.6.9 104 8/26/2026
1.6.8 102 8/26/2026
1.6.7 107 8/24/2026
1.6.6 112 8/23/2026
1.6.5 130 8/22/2026
1.6.4 132 8/16/2026
1.6.3 103 8/14/2026
1.6.2 102 8/13/2026
1.6.1 124 8/4/2026
1.6.0 122 7/31/2026
Loading failed

Minor rather than patch: two behaviour changes, both spec-correct, both able to change what an
existing stylesheet does. **Read the first section before upgrading.**

Takes **PhoenixmlDb.XQuery 1.8.0** and PhoenixmlDb.Core 1.7.0.

### Behaviour changes — read this before upgrading

**1. `streamable="true"` and `streamable="1"` are now honoured.**

XSLT 3.0 types `@streamable` as a boolean, but previous releases compared it against the literal
string `"yes"`. Any other spelling — including `true`, `1`, and `yes` with surrounding whitespace —
was silently treated as not streamable, and such stylesheets ran unstreamed.

**If you use one of these spellings, this release changes how your stylesheet executes.** It will
now genuinely stream, which is faster and uses less memory, but streaming support has known gaps
that unstreamed execution does not: some constructs produce different output rather than raising
an error. If you see unexpected results after upgrading, setting the mode or source-document to
`streamable="no"` restores the previous behaviour, and we would like to hear about the case.

Of the nineteen conformance cases this change exposed, **eleven are already fixed in this same
release** — the change and most of its fallout ship together.

**2. Built-in functions now enforce declared argument cardinality** (from PhoenixmlDb.XQuery
1.8.0). `substring('abc', ())` now raises `XPTY0004` rather than returning `""`. This applies to
every built-in; see that package's notes.

### Silent wrong answers — fixed

Each of these produced a well-formed, plausible result with no error.

- **A streaming aggregate answered from nothing.** Under a streamable mode, a `match="/"` template
 aggregating over the stream computed from no input at all: `count(//PRICE)` gave `0`,
 `sum(//PRICE)` gave empty, whatever the document held. This is the default CLI path —
 `--no-stream` gave the same wrong answers.
- **`xsl:function cache="yes"` returned other calls' results.** The memo key was a string
 concatenation, so `f((1,2))` and `f((3,4))` shared an entry, as did `f('1')` and `f(1)`. Present
 in every release since 1.1.0.
- **Accumulators read a later-declared accumulator one node late.** End-phase rules ran in
 declaration order, so reading another accumulator's after-value at the same node returned the
 *previous* node's value. Declaration order decided correctness. Also present since 1.1.0. A
 two-accumulator cycle now correctly raises `XTDE3400` instead of resolving to stale data.
- **`xsl:function` declared `as="item()*"` silently lost element nodes.** Writing the type
 explicitly — the careful habit — selected the broken path; omitting `as` worked.
- **`xsl:merge` silently merged one of two sources.** A relative `for-each-source` URI resolved
 against the wrong base, and an unretrievable source was skipped without an error. Now
 `FODC0002`.
- **`xsl:text` moved to the end of any untyped variable.**
- **Streamed shallow-copy produced malformed XML** — siblings nested inside one another, with the
 outer element left unclosed.
- **`fn:serialize` emitted `xmlns:p=""`**, so its output did not reparse.

### Added

- **`xsl:mode warning-on-no-match` now warns.** It was parsed, validated, and discarded. The
 built-in template rule is silent by design, so a node no template matched yields text where
 markup was expected with no indication — this is the mechanism for catching that.

### Also fixed

- `xsl:merge` key comparison uses the key's collation rather than codepoint order.
- `xsl:merge` rejects a streamable source that crawls or sorts; duration keys compare by length.
- A schema importing the XML namespace without a location now loads — previously
 `xsl:import-schema` failed outright and the stylesheet would not load at all.
- Abstract component invocation raises `XTDE3052` rather than "not found".
- Numerous error codes corrected: `XTSE3430`, `XTDE3362`, `XTDE3160`, `XTTE3210`, `XTSE3155`,
 `XTSE3080`, `SESU0013`, `XTSE0010`, `XTSE0730`, `XTDE1162`, `XTSE2210`, `XTDE3510`.
- Streaming: ancestors are linked on the striding path, `position()` counts per parent, a
 suppressed subtree no longer closes its ancestor early, and a matched element's children are
 delivered rather than dropped.
- CLI: an `xsl:result-document` `href` that is already a URI is written to the right path.

### Conformance

**W3C XSLT 3.0: 10,292/10,630 (96.82%)** — a full-corpus run at the exact commit tagged for this
release, 2026-09-13, against `xslt30-test` @ `fddf1cf` in a Release build.

W3C QT3 **29,534/31,414 (94.02%)**, measured 2026-09-11 against `qt3tests` @ `201a6e4` from the
committed per-set baseline. That figure predates this release's XQuery bump and is a floor.

The engine pin moved from `PhoenixmlDb.XQuery` 1.7.0 to 1.8.0 in this release, and that bump was
measured as its own change: **full corpus at both commits, no per-set differences.** The
built-in cardinality change reaches nothing the XSLT corpus exercises.