Wednesday, July 25, 2012

XSLT : Fun with xslt and xpath with fop

So I wanted a generic, all things to all men style sheet transformation on my service call to generate a PDF report for any xml message.

I had to do this using XSLT 1.0 booo hiss. This really make things harder. So here is what I learned:

So the first thing I needed was a JAXB transform from incoming object to xml.


        JAXBContext context = JAXBContext.newInstance(xmlObject.getClass());
        Marshaller marshaller = context.createMarshaller();
        StringWriter sw = new StringWriter();
        marshaller.marshal(xmlObject, sw);
        IOUtils.closeQuietly(sw);
        return sw.toString();



The next thing was passing parameters (a report title)


            Transformer transformer = tFactory.newTransformer(xsltSrc);
            transformer.setParameter("ReportTitle", "Report Title");

<xsl:param name="ReportTitle" select="'None'"/>
<xsl:value-of select="$ReportTitle"/>


Making the element tag names human readable


  <xsl:template name="ConvertToReadable">
    <xsl:param name="text"/>
    <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
    <xsl:if test="$text != ''">
      <xsl:variable name="letter" select="substring($text, 1, 1)"/>
      <xsl:choose>
        <xsl:when test="contains($vUpper, $letter)">
          <xsl:value-of select="concat(' ', $letter)"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$letter"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:call-template name="ConvertToReadable">
        <xsl:with-param name="text" select="substring-after($text, $letter)"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>




Formatting and checking dates : this was a little tricky I had to use EXSLT (which is included if you use xalan) add the following namespace : xmlns:datetime="http://exslt.org/dates-and-times" and


 <xsl:when test="datetime:date(.) != ''">
   <xsl:value-of select="datetime:format-date(., 'yyyy/MM/dd HH:mm')"/>
 </xsl:when>


Formatting and checking numbers:

<xsl:when test="number(.) = .">
  <xsl:value-of select="format-number(., '#######.#####')"/>
</xsl:when>