Welcome to CQBlueprints - A resource for your Adobe CQ 5.4, 5.5, 5.6 and AEM6 projects. Get your CQ project on the right track.

How can I configure the PDF rewriter?


CQ has a built in rewriter that automatically renders a page as a PDF through Apache FOP (with composition defined in XSL) whenever the extension .pdf is requested.  Creating a script in a template component with the name pdf.<script extension>, such as pdf.jsp, can override this, but then the pdf must be manually created and delivered though a library such as Apache PDFBox.  This document instructs you how to use the out of the box functionality of CQ to configure the PDF rewriter.


The easiest method is to simply update the .xsl file used by default with CQ.  This is found in the repository at /libs/wcm/core/content/pdf/page2fo.xsl.  Write the xsl-fo and the xslt the way you would normally.  See the XSL section for more details.


The actual code that runs the CQ PDF rewriter is contained in the OSGI bundle called "Day Communique 5 Rewriter" (com.day.cq.cq-rewriter).  Specifically, the package com.day.cq.rewriter.xml within the bundle holds the classes relevant to PDF rewriting.  These classes are called through two different services in Apache Felix.  One service controls the ComponentFactory and the other controls the TransformerFactory.  To do some of the customizations described here, you will need to modify these bundles or services or create new bundles and services similar to these.

Rewriter Configuration

The rewriter configuration is found in the repository at /libs/cq/config/rewriter/pdf.  More documentation on this configuration can be found here.  If you have added new bundles or services, or have renamed the default services, this is where you must reconfigure sling to use the modified services.  Note also that, by default, the configuration node has two children, most importantly the child "transformer-xslt."  This node contains a property called "source" which defines the path in which the transformer searches for the .xsl file.  The SourceResolver that controls the path search for this field is com.day.cq.rewriter.xml.SourceResolverImpl, and allows the following namespaces:

  • file: Uses the org.apache.excalibur.source.factories.FileSourceFactory class, which searches the server's file system.
  • resource: Uses the org.apache.excalibur.source.factories.ResourceSourceFactory class, which searches the resources from the classloader.
  • sling: Uses the com.day.cq.rewriter.xml.SlingResourceSourceFactory class, which searches the repository.
  • *: Uses the org.apache.excalibur.source.factories.URLSourceFactory class, which searches a url.

Note that, by default, you are only able to set a single .xsl file that will be used for all PDFs.  See the Allowing Multiple XSL Files for details on changing this.


The default location for the .xsl file controlling the pdf is /libs/wcm/core/content/pdf/page2fo.xsl.  This can be changed by modifying the rewriter configuration.  The only parameter set by default is "resource", which is a string that holds the current resource's path.  If you need to get simply the resource name, you can use this .xsl code to retrieve it.

//CALLED USING <xsl:call-template name="trim"> //NOTE THAT THE -11 IS TO ELIMINATE THE "/jcr_content" AT THE END OF THE STRING <xsl:with-param name="str"><xsl:value-of select="substring($resource,0,string-length($resource)-11)"/></xsl:with-param> </xsl:call-template> //USED FOR RECURSIVELY TRIMMING THE RESOURCE PARAM TO GET THE PAGE NAME <xsl:template name="trim"> <xsl:param name="str" /> <xsl:choose> <xsl:when test="contains($str, '/')"> <xsl:call-template name="trim"> <xsl:with-param name="str"><xsl:value-of select="substring-after($str, '/')"/></xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$str"/> </xsl:otherwise> </xsl:choose> </xsl:template>

To send additional parameters to the xsl, see the Adding Parameters section.

Allowing Multiple XSL Files

The CQ code controlling the rewriter have been hardcoded to look for the "source" property on the "transformer-xslt" node (found at /libs/cq/config/rewriter/pdf/transformer-xslt by default).  To allow multiple .xsl files to be used based on some other consideration (notably the current resource's "cq:template" or "sling:resourceType" properties), you must modify the com.day.cq.rewriter.xml.XSLTTransformer class.  Specifically for basing the xsl on the template, the init method must change from simply getting "source" to finding out what template is used and searching for the config for that template. For example,

public void init(ProcessingContext context, ProcessingComponentConfiguration config) throws IOException
    Node currentNode = context.getRequest().getResource().adaptTo(Node.class);
    String template = currentNode.hasProperty("cq:template") ? currentNode.getProperty("cq:template").getString() : "source";
    template = template.substring(template.lastIndexOf("/")+1);
    String src = (String)config.getConfiguration().get(template);
    if (src == null)
    src = (String)config.getConfiguration().get("source");
    if (src == null)
    throw new RuntimeException("Source is missing.");
    this.resolver = new SourceResolverImpl(context.getRequest().getResourceResolver(), context.getRequest(), context.getResponse());
    this.inputSource = this.resolver.resolveURI(src);
    this.xsltProcessor = new XSLTProcessorImpl(this.resolver);
    this.resource = context.getRequest().getResource();

Adding Parameters

The only parameter sent in the xsl request is the parameter "resource," which holds a string of the current resource's path.  In order to add additional parameters to the xsl request, you must modify the com.day.cq.rewriter.xml.XSLTTransformer class.  At the end of the "setContentHandler" method, simply add code similar to this:

this.transformerHandler.getTransformer().setParameter("resourceName", this.resource.adaptTo(Node.class).getName());

Then, in the .xsl file, simply include another parameter.

<xsl:param name="resourceName"/>

Do you find the information on this site useful? Do you think we should add an article on a specific subject? We'd like to hear from you. Please drop us an email @ info@headwire.com

Search CQ Related Information