Renderers

List of available renderer adaptors

Overview

Lavoisier does all it can to provide a view matching to the requested extension, but you have to know that you can refine this behaviour using a dedicated xml tag <pre-renderers>, appended as the last child of the tag <view>. First let's go a little further by exploring the render categories.

They are 3 categories of renderers :

  • tree-based renderers: xml, yaml, json. These renderers generate output directly from the full XML data
  • document-based renderers: html, pdf. If the parameter 'stylesheet' is set, then these renderers generate output directly from the full XML data. Else they generate output from the intermediate 2D array representation of the data view (see pre-renderers).
  • 2D-based renderers: csv, xls, chart. These renderers generate output from the intermediate 2D array representation of the data view (see pre-renderers).

Override browser rendering
In order to override browser rendering when "accept" query field is not provided, you can set the parameter "contentType" of the DefaultRenderer plug-in. Usage example:
        <renderers>
            <renderer type="DefaultRenderer">
                <parameter name="contentType">image/svg+xml</parameter>
            </renderer>
        </renderers>

Recommendation for writing rendering stylesheet
Here are some recommendations to follow when writing a XSL stylesheet for view rendering:
  • you can use xml output for specific cases, text is not supported
  • use template rules rather than named templates or for-each statements, in order to render XPath result as well.
  • add template rules for rendering elements <entries> and <entry> (from namespace http://software.in2p3.fr/lavoisier/entries.xsd), in order to render XPath result as well.
  • links to path (instead of URL) that are interpreted by the XSL processor must match "/lavoisier/{viewId}[{/xpath}]", in order to enable server-side generated rendering.

A full example

Pre-requisite
IN ORDER TO AVOID BROKEN LINKS, THIS PAGE SHOULD BE BROWSED THROUGH A LAVOISIER INSTANCE, INSTALLED ON YOUR LOCALHOST FOR EXAMPLE: http://localhost:8080/lavoisier/doc/projects/lavoisier/wiki
Introduction
This example uses earnings report data:
<report>
    <earnings year="2010">
        <sales month="01">304</sales>
        <sales month="02">310</sales>
        <sales month="03">370</sales>
        <sales month="04">375</sales>
    </earnings>
    <earnings year="2011">
        <sales month="01">321</sales>
        <sales month="02">400</sales>
        <sales month="03">414</sales>
        <sales month="04">401</sales>
    </earnings>
    <earnings year="2012">
        <sales month="02">302</sales>
        <sales month="02">310</sales>
        <sales month="03">313</sales>
        <sales month="04">350</sales>
    </earnings>
</report>
The following request /lavoisier/report (or /lavoisier/report?accept=html) will give you a clean html table. Lavoisier has applied a default rendering providing an xsl stylsheet which have been executed by the browser. You can notice that you can browse the tree structure clicking on cell links. Using CTRL+U shortcut in your browser you can check that your original data have not changed, nothing more normal, it's only rendering ! Now you can try to set the 'accept' parameter to all the supported mime type.
Refining for 2D array category
cvs is a 2D array category, and if you try to get your data rendered with this format using /lavoisier/report?accept=csv, you should have to download a file containing inconsistent data regarding to your original tree structure:
Position,earningsYear
1,2010
2,2011
3,2012
Tree structure of the original data can't be automatically converted to a consistent 2D array format in this case. But you might want to provide this data in a simple table format instead of a tree structure. So we use the pre-renderers section to provide a clean csv file. Please copy paste this pre-renderers configuration at the end of your view in app/views/*.xml file and restart Lavoisier.
        <pre-renderers>
            <title>"Earnings report"</title>
            <row foreach="report/earnings/sales">
                <column label="date">concat(../@year,'-', @month)</column>
                <column label="nb_products" unit="nb">text()</column>
            </row>
        </pre-renderers>
Consequently CSV rendering (/lavoisier/report?accept=csv) now contains more useful information:
date,nb_product
2010-01,304
2010-02,310
2010-03,370
2010-04,375
2011-01,321
2011-02,400
2011-03,414
2011-04,401
2012-02,302
2012-02,310
2012-03,313
2012-04,350
You can also configure a given renderer or make it customizable by the user:
        <renderers>
            <renderer type="HTMLRenderer">
                <parameter name="template">report.xsl</parameter>
            </renderer>
            <renderer type="ChartDeprecatedRenderer">
                <parameter name="type" eval="$chart"/>
            </renderer>
        </renderers>
If default value of view argument 'chart' is set to 'line' (<argument name="chart">line</argument>), then /lavoisier/report?accept=chart will display a line-chart, while /lavoisier/report?accept=chart&chart=column will display a bar-chart.
Refining for document category
Finally, it could be useful to design a dedicated html rendering which could not be obtained with the default behaviour. Lavoisier allows to do that writing an xslt stylesheet. In this example we will use the default lavoisier css which is a twitter bootstrap theme, retrieved from a dedicated Lavoisier view. First, create a report.xsl file in directory 'etc/' and copy-paste the following code inside:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"></xsl:output>
    <xsl:param name="table"></xsl:param>

    <xsl:template match="/">
        <html>
            <xsl:call-template name="head"></xsl:call-template>
            <body data-spy="scroll" data-target=".subnav" data-offset="50">
                <xsl:call-template name="navbar"></xsl:call-template>
                <div class="container fluid" style="margin-top:80px">
                    <h1>Number of products by year/month</h1>
                    <xsl:apply-templates select="/report/earnings"></xsl:apply-templates>
                </div>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="earnings">
        <table>
            <xsl:attribute name="class">table <xsl:value-of select="$table"></xsl:value-of></xsl:attribute>
            <tr>
                <td>
                    <xsl:attribute name="rowspan">
                        <xsl:value-of select="count(sales)+1"></xsl:value-of>
                    </xsl:attribute>
                    <h2>
                        Year
                        <br></br>
                        <xsl:value-of select="@year"></xsl:value-of>
                    </h2>
                </td>
            </tr>
            <xsl:apply-templates select="sales"></xsl:apply-templates>
        </table>
        <br></br>
    </xsl:template>

    <xsl:template match="sales">
        <tr>
            <td>
                <xsl:value-of select="@month"></xsl:value-of>
            </td>
            <td>
                <xsl:value-of select="."></xsl:value-of>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>
Then copy-paste this renderers configuration at the end of your view in app/views/*.xml file and restart Lavoisier:
        <renderers>
            <renderer type="HTMLRenderer">
                <parameter name="template">xsl/report.xsl</parameter>
                <parameter name="parameters">
                    <entry key="table" eval="$table"/>
                </parameter>
            </renderer>
        </renderers>
If default value of view argument 'table' is set to 'table-striped' (<argument name="table">table-striped</argument>), then /lavoisier/report?accept=html will display a table with zebra-striping rows, while /lavoisier/report?accept=html&table=table-bordered will display a table with borders and rounded corners.