Update: Daisy 1.5 contains this SVG support out-of-the-box, including some improvements such as automatic resizing of the embedded SVG, and SVG rendering support in books. I'll leave this article here as background information, and because it serves as an example for similar extensions.
This tutorial shows an approach for handling SVG graphics in Daisy. It also serves as an introduction to defining document types, using document-type specific styling and creating a Daisy Wiki extension.
You need the Daisy 1.4 final release for this.
Let's start by creating a part type and document type specifically for SVG documents.
First go to the administration pages:
Then create a part type called SvgData:
Then create a document type called "SvgDocument":
Go back to some Daisy site by selecting the "Daisy Home" link in the top right corner, and then selecting some site of your preference.
Select "New Document" in the navigation, and then choose SvgDocument from the list.
You now see the document editor with an upload facility (instead of the usual HTML editor).
Save this test svg document (image/svg+xml, 1.1 kB, info) to your local drive, and then upload it in the new document.
Check that the mime type is correctly specified as image/svg+xml.
Change the name of the document to something of your choice, e.g. "Test SVG".
Press Save to save the new document.
After this you'll simply see the Test SVG document with a download link to download the SVG image. If you use a browser that can render SVG images, you can click that link to see the image.
| Click to enlarge |
We would like to have this image displayed inline, and rendered as a PNG image for browsers that do not support SVG.
Here is where the extension mechanism of the Daisy Wiki comes into play. A Daisy Wiki extension is simply a custom Cocoon sitemap that can implement anything you like. Don't be afraid if you don't know Cocoon, all you need to know is below.
For rendering SVG to a raster image format, we will make use of Batik. Cocoon provides Batik integration, however this is part of an optional "block" that is not included by default with Daisy. Therefore, download the following two jars:
and put them in the following directory:
DAISY_HOME/daisywiki/webapp/daisy/WEB-INF/lib
Restart the Daisy Wiki after adding these jars.
Now create a new subdirectory called svg as child of the following directory:
DAISY_HOME/daisywiki/webapp/daisy/sites/cocoon/
so that you thus get:
DAISY_HOME/daisywiki/webapp/daisy/sites/cocoon/svg
In this newly created directory, create a file called sitemap.xmap with the following content:
<?xml version="1.0"?>
<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
<map:components>
<map:serializers default="html">
<map:serializer name="svg2png"
src="org.apache.cocoon.serialization.SVGSerializer"
mime-type="image/png"
logger="sitemap.serializer.svg2png"/>
</map:serializers>
</map:components>
<map:views>
</map:views>
<map:resources>
</map:resources>
<map:pipelines>
<map:pipeline type="caching">
<map:parameter name="outputBufferSize" value="8192"/>
<map:match pattern="rendersvg">
<map:generate src="daisy:{request-param:documentId}@{request-param:branch}
:{request-param:language}:{request-param:version}!{request-param:part}"/>
<map:serialize type="svg2png"/>
</map:match>
</map:pipeline>
</map:pipelines>
</map:sitemap>
The content of the src attribute (daisy:...) must be on one line, without whitespace in between. It has been split in the listing above since otherwise it wouldn't fit on everyones screen.
Note the following things in this sitemap (excuse the very poor Cocoon explanation, but is is sufficient to comprehend what is done here):
daisy:<documentId>@<branch>:<language>:<version>!<partTypeName>
which is thus similar to the normal daisy: links that are embedded in Daisy documents, with the exception that a part type is specified on the end. As with normal daisy links, the branch, language and version specifications are optional.
Now we can try out this extension. In a webbrowser, enter an URL similar to the following one (on one line of course):
http://localhost:8888/daisy/coolsite/ext/svg/rendersvg ?documentId=3&branch=main&language=default&version=live&part=SvgData
But change it according to your configuration:
After loading that URL, you should see the rendered SVG image, which looks
like this:

Now we would like to have the SVG image displayed directly when we go to the SVG document in Daisy. For this, we will create a document type specific stylesheet. This is a custom XSLT that is used for rendering documents that are of a certain document type.
This is done as follows: create a file called SvgDocument.xsl (= name of the document type + ".svg" extension) in the following directory:
DAISY_HOME/daisywiki/webapp/daisy/resources/document-styling/default/html
Put the following inside the SvgDocument.xsl file and save it:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://outerx.org/daisy/1.0">
<xsl:import href="daisyskin:xslt/document-to-html.xsl"/>
<xsl:template match="d:document">
<br/>
<img src="{$documentBasePath}ext/svg/rendersvg?documentId={@id}&branch={@branch}
&language={@language}&version={@dataVersionId}&part=SvgData"/>
<br/>
</xsl:template>
</xsl:stylesheet>
Again, the content of the src attribute of the <img> tag should be on one line, wihtout whitespace in between.
If you now go to the SVG document, you should see the rendered image:

Some browsers, such as Firefox 1.5 and Konqueror, and other browsers with some plugin installed, can directly render SVG. We can easily take advantage of this by slightly modify our SvgDocument.xsl:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://outerx.org/daisy/1.0">
<xsl:import href="daisyskin:xslt/document-to-html.xsl"/>
<xsl:template match="d:document">
<br/>
<object data="{$documentBasePath}{@id}/version/
{@dataVersionId}/part/SvgData/data/abc.svg" type="image/svg+xml">
<img src="{$documentBasePath}ext/svg/rendersvg?documentId={@id}&branch={@branch}
&language={@language}&version={@dataVersionId}&part=SvgData"/>
</object>
<br/>
</xsl:template>
</xsl:stylesheet>
Again, put the content of the data attribute and the src attribute on one line.
By using the <object> tag, browsers which understand SVG will directly render the SVG document, and ignore the content of the <object> tag. Other browsers which don't understand SVG will render the <img> tag, and thus delegate the rendering of the SVG to our Daisy Wiki extension.
As you will see if you try this, the <object> frame will likely not be correctly sized and thus cause a part of the image to be clipped or scrollbars to appear.
The Daisy Wiki renders PDF images by transforming the documents into XSL-FO which is then processed by Apache FOP into a PDF. Apache FOP happens to support SVG too (via Batik again), which allows the SVG to be rendered inside the PDF. The nice thing about this is that the SVG will be embedded as a vector image, not as as bitmap image, so that is doesn't take much space and the edges of the lines and curves are sharp when zooming in and/or printing, as shown in the following illustration.

Create a file called SvgDocument.xsl in the following directory (this directory might not yet exist, create it if needed):
DAISY_HOME/daisywiki/webapp/daisy/resources/document-styling/default/xslfo
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://outerx.org/daisy/1.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:import href="daisyskin:xslt/document-to-html.xsl"/>
<xsl:param name="documentBasePath"/>
<xsl:template match="d:document">
<fo:external-graphic src="url('http://localhost:8888/{$documentBasePath}{@id}
/version/{@dataVersionId}/part/SvgData/data?branch={@branch}&language={@language}')"/>
</xsl:template>
</xsl:stylesheet>
Put the value of the src attribute on one line.
Note that we need to do something here which is not very nice: the src is hardcoded to fetch the image from "http://localhost:8888". Thus this will send out a new HTTP request to fetch the image. Unfortunately, with the current version of FOP this is the only option we have. Since this is a new HTTP request, it will also not use the browsers' session and thus fetch the image as guest user. If the SVG document is not accessible for the guest user, this will pose a problem.
By the way, the same is done for normal Daisy images, however these are processed by a special transformer which will insert the correct server name and port, and add the sessionid of the current user (if any) to the URL.
Now that we have the SVG image rendered, we would like to embed it inside some other document in Daisy. This can be done by simply using the document include feature. If you don't know how this works, follow these instructions:
daisy:3
There is also a button on the toolbar to look this up, if you don't remember the document ID.

As mentioned and seen, the image size needs to be specified when using the <object> tag or when embedding the image in PDF. This could be done by adding fields for this purpose to the SvgDocument document type.
Instead of having to download/upload the SVG image for editing, for simple images it would be possible to use a browser-embedded SVG editor (if such a thing exists), which is possible through the custom part editors of the Daisy Wiki.
The technique we have used here can be applied to many other situations. In fact, it is already used by the "MultimediaObject" document type included with Daisy (from version 1.4) which allows embedding things such as flash and mpeg movies or audio streams. A nice application would also be charting: the chart data could be entered in a part (using some XML format, possibly edited with a custom part editor) and then dynamically rendered, for example by making use of fins.
| Name | Value |
|---|---|
| Category | Frontend (wiki) tutorials & extensions |
| 1. | Yes, I know this is not a valid URL format due to the illegal use of the at and colon characters. |