Skip to content
Wrap Saxon 9.X's HE's XSLT 2.0 processor for use in JRuby
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Wraps the Saxon 9 XSLT processor Java API so it's easy to use from your JRuby project, with an API modelled on Nokogiri's.

Saxon is a Java library, so saxon-xslt only runs under JRuby.

Gem Version Build Status Code Climate Test Coverage

You can find Saxon HE at and Saxonica at

Saxon HE is (c) Michael H. Kay and released under the Mozilla MPL 1.0 (


Add this line to your application's Gemfile:

gem 'saxon-xslt'

And then execute:

$ bundle

Or install it yourself as:

$ gem install saxon-xslt

Simple usage

require 'saxon-xslt'
transformer = Saxon.XSLT('/path/to/your.xsl'))
input = Saxon.XML('/path/to/your.xml'))
output = transformer.transform(input)

XSL parameters can be passed to #transform as a flat array of name, value pairs, or as a hash. name can be either a string or a symbol, e.g.

output = transformer.transform(input, ["my-param", "'my-value'",
                                       :'my-other-param', "/take-from@id"])

# or

output = transformer.transform(input, {"my-param" => "'my-value'",
                                       :'my-other-param' => "/select-from@id",
                                       my_third_param: "'value-again'"})

For those familiar with the Saxon API, names are passed directly to the QName constructor.

Values are evaluated as XPath expressions in context of the document being transformed; this means that, to pass a string, you must pass an XPath that resolves to a string, i.e. "'You must wrap strings in quotes'"

Differences between Saxon and Nokogiri

Saxon uses a Processor class as its central object: it holds configuration information and acts as a Factory for creating documents or XSLT stylesheet compilers. Unless you need to tweak the config you don't need to worry about this – saxon-xslt creates a shared instance behind the scenes when you call Saxon.XSLT or Saxon.XML. If you need to change the configuration you can create your own instance of Saxon::Processor and pass it an open File pointing at a Saxon configuration file. (See!configuration/configuration-file for details of the configuration file.) Once you have a Saxon::Processor instance you can call the XML and XSLT methods on it directly:

require 'saxon-xslt'
processor = Saxon::Processor.create('/path/to/config.xml'))
transformer = processor.XSLT('/path/to/your.xsl'))
input = processor.XML('/path/to/your.xml'))
output = transformer.transform(input)

System IDs

XML has this idea of 'Public' and 'System' identifiers for documents. The public ID is a kind of abstract name and the system ID is a URI, for example:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

There the Public ID is -//W3C//DTD HTML 4.01 Transitional//EN and the System ID is An XML or XSLT processor uses the System ID as a base URI for resolving linked objects, e.g. <xsl:import> or <xsl:include> calls with relative URIs.

With Nokogiri the System ID for a document is inferred from its file path, if you hand in a File object to Nokogiri::XML. With saxon-xslt you can also explicitly set the System ID:

xslt = Saxon.XSLT("<xsl:stylesheet>...</xsl:stylesheet>",
  system_id: "/path/to/resources/file.xsl")

So, if you have other XSLT stylesheets in /path/to/resources/ then your dynamically generated XSLT can refer to them with import statements like <xsl:import href="other_stylesheet.xsl"/>.

Saxon versions (HE, PE, EE)

saxon-xslt 0.8.2 includes Saxon HE - you don't need to download Saxon yourself. Saxon PE and EE are paid-for versions with more features.

If you have a license for Saxon PE or EE, then you can use them by passing their location and the location of your .lic license file in as follows:

require 'saxon-xslt'

# Tell us where your Saxon Jars are.
# Create a licensed Configuration object
config = Saxon::Configuration.create_licensed('/path/to/saxon-license.lic')
# Create a Processor from your licensed Configuration
processor = Saxon::Processor.create(config)
# Go!
transformer = processor.XSLT('/path/to/your.xsl'))


  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request
You can’t perform that action at this time.