XQuery/XSL-FO SVG
Motivation
[edit | edit source]You want to convert XML into PDF and embed SVG graphics in the output.
Method
[edit | edit source]eXist since version 2 supports placing svg in fop rendered pdf out of the box, the only step being to activate the XSLFO module before building the source:
echo "include.module.xslfo = true" > $EXIST_HOME/extensions/local.build.properties
Beware: On headless *nix systems, make sure that there is no DISPLAY environment variable set, when eXist-db is started, otherwise the apache batik svg renderer may throw an exception.
Sample XQuery
[edit | edit source]Highlights of the xquery: The FO is created from an xsl transform: I know, this could be done with xquery, but I can reuse the xsl in other places. The document is found through a search. The xsl stylesheet resides in "views", as the pdf.xq does. I create lots of variables, but its better that way. Filename deduced from request. There may be errors, as I stripped down working code! It may be overly complicated due to my ignorance of xquery features. I think you will find your way. Application directory laid out as advised in the XRX wiki.
let $host := "http://localhost:8080/exist/rest/"
let $home := "/db/apps/myApp"
let $match := collection(concat($home, "/data"))//item[@uuid=$uuid]
let $coll := util:collection-name($match)
let $file := util:document-name($match)
let $xsls := concat($home, "/views/foPDF.xsl")
let $rand := concat("?", util:random())
let $params :=
<parameters>
<param name="svgfile" value="{$host}{$home}{$file}.svg"/>
<param name="rand" value="{$rand}"/>
</parameters>
let $tmp := transform:transform(doc(concat($coll, "/", $file)), doc($xsls), $params)
let $pdf := xslfo:render($tmp, "application/pdf", (), ())
(: substring-afer-last is in functx :)
let $fname := substring-after(request:get-path-info(), "/")
return response:stream-binary($pdf, "application/pdf", $fname)
Another, possibly higher performance, way to source the svgfile by the xmldb:exist qualifier:
let $host := "xmldb:exist://"
Highlights of the XSL:
[edit | edit source]<!-- passed in parameter, a fully qualified URI to the SVG file, eg:
"http://localhost:8080/exist/rest//db/apps/myApp/data/Some.svg"
or in exist-db "xmldb:exist///db/apps/myApp/data/Some.svg"
-->
<xsl:param name="svgfile" select="''"/>
<!-- passed in parameter, value eg: "?123", changes with every call
used to force fop to reread the svg file each time
starts with ? to be discarded in the end...
can be left blank to have fop cache the svgfile
-->
<xsl:param name="rand" select="''"/>
<!-- place SVG in PDF output -->
<fo:block-container>
<fo:block>
<fo:external-graphic src="{$svgfile}{$rand}"/>
</fo:block>
</fo:block-container>