Skip to content

JavaScript bindings for libxslt compiled to WebAssembly

License

Notifications You must be signed in to change notification settings

jeremy-code/libxslt-wasm

Repository files navigation

libxslt-wasm

A WebAssembly port of libxslt (XSLT 1.0) and libxml2 for Node.js using Emscripten.

If you're looking for a well-maintained JavaScript XML/XSLT library, you should consider using one of the following libraries instead:

XML:

  • htmlparser2 (and its complements cheerio, domutils, etc.) - Fast & forgiving HTML/XML parser
  • fast-xml-parser - Validate XML, Parse XML, Build XML without C/C++ based libraries
  • @xmldom/xmldom - A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module
  • libxml2-wasm - WebAssembly-based libxml2 JavaScript wrapper

XSLT:

Installation

npm install libxslt-wasm # npm
yarn add libxslt-wasm    # yarn
pnpm add libxslt-wasm    # pnpm

Usage

This library is fairly niche and is not intended to be a drop-in replacement for other libraries. Its intended use cases are:

  • Applying XSLT to XML documents and NOT for general-purpose XML parsing or querying (e.g. XPath, DOM, etc.)
  • Applying XSLT 1.0 and not XSLT 2.0/3.0
  • Replicating the behavior of browsers (specifically WebKit and Blink which use libxslt) in Node.js
  • Parsing an XSLT stylesheet that includes a number of external files (via xsl:include, xsl:import) that would be infeasible to download beforehand with relative URLs
  • Capable of enabling EXSLT modules and their functions

i.e. if all the aforementioned libraries can't transform your XML document but the xsltproc CLI tool can do so easily without any issues, you might consider using this library.

import { writeFile } from "fs/promises";

import { XmlDocument, XsltStylesheet } from "libxslt-wasm";
import { registerModule } from "libxslt-wasm/exslt";

registerModule("common"); // Register EXSLT common module

using doc: XmlDocument = await XmlDocument.fromFileOrUrl(
  "https://dailymed.nlm.nih.gov/dailymed/services/v2/spls/2b4255a7-f9f5-4235-8dbb-b0f03acbd624.xml",
);
// Equivalent to `await XsltStylesheet.fromFileOrUrl("https://www.accessdata.fda.gov/spl/stylesheet/spl.xsl");`
using xsltStylesheet: XsltStylesheet | null =
  await XsltStylesheet.fromEmbeddedXmlDocument(doc); // From <?xml-stylesheet?> processing instruction

if (xsltStylesheet === null) {
  throw new Error("Invalid XSLT stylesheet");
}

using result: XmlDocument = await xsltStylesheet.apply(doc, {
  // Set <xsl:param> values
  "show-data": "/..",
});

await writeFile("output.xml", result.toString({ format: true })); // As XML
await writeFile("output.html", result.toHtmlString({ format: true })); // As HTML

However, there are some caveats:

  • Top-level await is required (see src/internal/module.ts) which is only avaliable in Node.js 14.8+ and in ECMAScript modules (ESM)
  • JavaScript Promise Integration (JSPI) must be enabled on Node.js via --experimental-wasm-jspi (v22+) or --experiment-wasm-stack-switching (v19.2+).
    • Furthermore, since this library operates by using JSPI to intercept any HTTP requests with Node.js fetch (v18+), some functions in this library return a Promise
  • Currently, since NODERAWFS is enabled to intercept file system calls with Node.js functions, this library currently only works on Node.js. While it could be modified to work on browsers, that would be a niche use case since all mainstream browsers already have both XSLT transformation and the XSLTProcessor API built-in
  • Since this library is a WebAssembly port of libxslt, it does not support the XSLT 2.0/3.0 or XQuery specifications
  • To interact with the compiled WebAssembly memory, wrapper classes are provided (XmlDocument, XsltStylesheet, etc.) that must be disposed of after use (either declaratively with the using statement or imperatively with the .close() method) to prevent memory leaks

License

This project is licensed under the MIT License - see the LICENSE file for details. It makes use of the following libraries: