XQuery/XSL-FO SVG

MotivationEdit

You want to convert XML into PDF and embed SVG graphics in the output.

MethodEdit

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 XQueryEdit

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

<!-- 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>
Last modified on 22 September 2013, at 09:46