Goals
Re-evaluate: what can XSLT do now that’s
in the pipeline space? How does it compare in difficulty?
Oil the Machine
Intro: here to talk about techniques that can make production workflow
go more smoothly, not to re-implement XProc.
Run XSLT
fn:transform() inspired this talk.
You can invoke another stylesheet from within XSLT .
The result is returned in a map.
fn:transform() changes the scope of XSLT.
Now you can use XSLT to coordinate groups of external transformations.
Why XSLT ?
An XSLT-only consulting client needed EPUB3 generation;
Fewer tools, processes, languages, technologies.
Become the Machine
Gears © Animale38 by permission
Areas
Run XSLT (obvious, but…)
Validation…
Queries…
External processes…
Zip, EPUB , EXP ath
Reading/writing
Inclusions, Exclusions, Conclusions
Validation
There’s no version of fn:document() that has options like whether to
do DTD validation, Schema validation, Schematron, etc.,
but some XSLT engines may have extensions or options for this.
Queries
There’s no fn:query() in XSLT as standard, although there’s saxon:query().
p:query is also an optional step in XProc.
External Commands
Again optional in XProc.
XSLT that runs Perl
<xsl:message xmlns:system="java:java.lang.Runtime?void=this">
<xsl:value-of select=" (
system:exec(system:getRuntime(), '/bin/perl -f /tmp/insecure.pl', ()),
''
)[2] " />
<xsl:value-of select="doc('/tmp/out.xml')//text()" />
Zip, EPUB , EXP ath
Read/write binary content and process Zip-format archives with
the EXP ath file:read(), file:write() and archive:*()
functions.
Updating a ZIP archive
<xsl:variable name="archive" as="xs:base64Binary"
select="archive:update(
$emptyarchive,
$alternatingvalues[(position() mod 2) eq 1],
$alternatingvalues[(position() mod 2) eq 0]
) " />
<xsl:value-of select="( file:create-dir($dirname),
file:write-binary($outputfilename, $archive) )[1] "/>
Writing Restriction
XSLT 2 introduced xsl:result-document
Can’t read from a URL you’ve written to.
fn:transform() returns a map containing not-actually-written documents,
and also can call a function for each resource.
Mitigation of Restriction
The restriction doesn’t aply to file:read(), file:write(),
file:write(fn:serialize($node))
etc.
You can “catch” the documents written by a called stylesheet
and write them out with file:write().
If we could override the entity resolver from within XSLT we could
arrange not to write files out at all but return in-memory copes for
the doc function.
Strategy
Replace each XProc step with an XSLT function;
Sequence replaced by nested function calls:
step1 → step2 → step3
can be rewritten as:
step3( step2( step1() ) )
Complications
Conditional operations and variables;
Catching written resources;
Multiple copies and flows.
The Wider Context
Is it a good idea?
Performance
Memory and Streaming
Contorted plumbing
Awesomeness of Saxon
Relation to EXPath Tasks
Questions