SoftCorporation LLC.

 

XSL EASY 3

If you are a beginner in XSL, please read “XSL Easy” and “XSL Easy 2” first, you can find there more information about basics of XSL (actually we are talking here about XSLT). But if you are already familiar with XSLT then you may find this document useful. Here you will find some examples of XSLT technique combined with Java and most of a time I’m going to devote to transformations from XML to HTML.

I’m using Apache’s Xalan processor to perform those transformations. Xalan is written in Java, it implements the W3C Recommendation XSLT Version 1.0 and incorporates the XML Path Language (XPath) Version 1.0. As well it works with Java Extensions and supports SAX model, so I believe it is a very good choice. You can download Xalan free from http://xml.apache.org/xalan-j/index.html

You can find the definitions of XSLT on the web http://www.w3.org/TR/xslt.html or in the book “XML Bible” by Elliot Rusty Harold, so in this document I do not speak what is XSLT but I would like to introduce here some practical examples.

Directory tree for our examples:

\sample\ - base XSL directory.
\sample\html\ - directory with XSL files used to create HTML content.
\sample\templates\ - directory with XSL files used as an included templates.
\sample\dtd\ - directory with DTD files.


Sample 1. DTD and Constants

Here is not quite usual but therefore very convenient way of storing the constants and some definitions in DTD file.

File: \sample\dtd\sample.dtd

<!--
Copyright (c) 2000 SoftCorporation LLC. All rights reserved.
-->

<!-- stylesheet -->

<!ATTLIST xsl:stylesheet version CDATA "1.0">
<!ATTLIST xsl:stylesheet xmlns:xsl CDATA "http://www.w3.org/1999/XSL/Transform">
<!ATTLIST xsl:stylesheet xmlns:lxslt CDATA "http://xml.apache.org/xslt">

<!-- symbols -->

<!ENTITY nbsp "&#160;">

<!-- constants -->

<!ENTITY BASE_URL "www.softcorporation.com">
<!ENTITY LOCATION "location">
<!ENTITY PNAME "ProductName">

<!-- expressions -->

<!ENTITY GET_BASE '<xsl:value-of select="sample:getBase()"/>'>
<!ENTITY SET_URL_BASE '<xsl:variable name="UrlBase">&GET_BASE;sample.oc</xsl:variable>'>
<!ENTITY GET_URL_BASE '<xsl:value-of select="$UrlBase"/>'>
!ENTITY PATH 'path=<xsl:value-of select="/&PATH;"/>'>


First of all couple words about “Stylesheet” part. You can put all stylesheet attributes in one place and it is especially convenient if you work with extensions. So in XSL file you have just <xsl:stylesheet> without attributes at all.

“Symbols” and “Constants” parts are clear. Symbols part has only definition of very often used in HTML &nbsp; entity and Constants part has definitions of your constants.

“Expressions” part is useful when you need to include some XSLT expression in many different places. Transformer replaces the entity reference in XSL document with corresponding expression.

If you need to use more then one DTD, here is an example how to do it.

<!DOCTYPE SAMPLE1 SYSTEM "../dtd/sample1.dtd" [
<!ENTITY % SAMPLE2 SYSTEM "../dtd/sample2.dtd">
%SAMPLE2;
<!ENTITY % SAMPLE3 SYSTEM "../dtd/sample3.dtd">
%SAMPLE3;
]>


Sample 2. Include the JavaScript

File: \sample\templates\template.xsl

<?xml version="1.0"?>
<!--
Copyright (c) 2000 SoftCorporation LLC. All rights reserved.
-->
<!DOCTYPE SAMPLE SYSTEM "../dtd/sample.dtd">
<xsl:stylesheet>
&SET_URL_BASE;

<xsl:template name="Sample_Form">

<xsl:text disable-output-escaping="yes"><![CDATA[
<script language="JavaScript" type="text/javascript">
<!--
function validate(form)
{
  blank_pattern=/^[ \t\n]*$/;
  if (blank_pattern.test(form.query.value))
  {
    alert("Please enter Query ...");
    form.query.focus()
    return false;
  }
  return true;
}
function submit(form)
{
  if (validate(form)) form.submit();
}
// -->
</script>
]]></xsl:text>

<form name="sample_form" action="{$UrlBase}" method="get" onsubmit="return validate(this)">
Enter Query:&nbsp;<input type="text" name="query" size="20"/>&nbsp;
<a href="javascript:submit(window.document.sample_form)">
<img src="/images/go.gif" alt="Send Query" align="absmiddle" border="0" width="28" height="17"/>
</a>
</form>
</xsl:template>

</xsl:stylesheet>

In this example we create a form with input field and use JavaScript to validate the input and submit the form if it is not empty. JavaScript text located inside CDATA section and inside <xsl:text disable-output-escaping="yes"> tag in order to save original formatting.


Sample 3. Using included templates

Let’s assume that we need to build a number of different HTML pages with some reports, which have the same header and similar content (as a table) and each report has the same bottom. It is very common task and it is good example of using included templates.

File: \sample\html\sample3.xsl

<?xml version="1.0"?>
<!--
Copyright (c) 2000 SoftCorporation LLC. All rights reserved.
-->
<!DOCTYPE SEARCH SYSTEM "../dtd/sample.dtd">
<xsl:stylesheet>
<xsl:include href="../templates/template3.xsl"/>
<xsl:include href="../templates/variables.xsl"/>
<xsl:output method="html" indent="no"/>
<xsl:strip-space elements="*"/>

<xsl:template match="response">
  <xsl:call-template name="Sample_Top">
    <xsl:with-param name="Sample"><xsl:value-of select="query"/></xsl:with-param>
  </xsl:call-template>
  <xsl:call-template name="Sample_Top"/>
  <xsl:for-each select="request">
    <xsl:call-template name="Sample_Table">
      <xsl:with-param name="data"><xsl:value-of select="data"/></xsl:with-param>
      <xsl:with-param name="title">Sample title</xsl:with-param>
    </xsl:call-template>
    <xsl:call-template name="Sample_List"/>
  </xsl:for-each>
  <xsl:call-template name="Sample_Bottom"/>
</xsl:template>

</xsl:stylesheet>

Here is an included XSL file /templates/template3.xsl

<?xml version="1.0"?>
<!--
Copyright (c) 2000 SoftCorporation LLC. All rights reserved.
-->
<!DOCTYPE SEARCH SYSTEM "../dtd/sample.dtd">
<xsl:stylesheet>
<xsl:include href="variables.xsl"/>

<xsl:template name="Sample_Top">
<xsl:param name="Sample">&GET_QUERY;</xsl:param>

<font size="4">
<b>Results for word: </b><font size="2"><xsl:value-of select="$Sample"/></font>
</font>
</xsl:template>


<xsl:template name="Sample_Bottom">

</xsl:template>

</xsl:stylesheet>

The most important in this example is a fact that we created our final XSL file using templates stored in another XSL file. I do not include here full text of /templates/template3.xsl because an idea is clear just from single "Sample_Top” template. The default value of the parameter “Sample” in this template is defined by &GET_QUERY; entity. You can store common templates in different files and reuse them including in necessary XSL documents.


Sample 4. Using Java Extensions

XSL has limitations of transformations. It is difficult and sometimes impossible to perform advanced logic in XSL. And there is no need to do it. You can use extensions to make it easy way. As well with extensions you can get additional data, for instance from Database, which may be necessary to complete your transformation.

In order to use Java extensions we have to define Java class as a namespace. Let’s assume that our java extension class stored in the file com.sc.extensions.Sample.class. So I add to our sample.dtd file next string:

<!ATTLIST xsl:stylesheet xmlns:sample CDATA "class:com.sc.extensions.Sample">

Actually it is enough in order to begin using our extensions but in order to get rid of including “sample” prefix in to the result file I want to add as well this string:

<!ATTLIST xsl:stylesheet exclude-result-prefixes CDATA "sample">

File: \sample\html\sample4.xsl

<?xml version="1.0"?>
<!--
Copyright (c) 2000 SoftCorporation LLC. All rights reserved.
-->
<!DOCTYPE SEARCH SYSTEM "../dtd/sample.dtd">
<xsl:stylesheet>
<xsl:output method="html" indent="no"/>
<xsl:strip-space elements="*"/>

<xsl:template match="sample">
<xsl:for-each select="price">
Price: <xsl:value-of select="sample:formatPrice(string(.))"/>
<br />
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Let’s take a look at <xsl:value-of select="sample:formatPrice(string(.))"/>. Our Java class has a method formatPrice, which takes a string as a parameter and returns back formatted string.

Here is a Java class:

/**************************************************
Copyright (c) 2000 SoftCorporation LLC. All rights reserved.
**************************************************/
package com.sc.extensions;

import java.io.*;
import java.lang.*;
import java.util.*;
import java.text.*;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;

public class Sample
{

  public static String getText(Node n)
  {
    StringBuffer sb = new StringBuffer();
    if (n != null)
    {
      for (n = n.getFirstChild(); n != null; n = n.getNextSibling())
      {
        String v = n.getNodeValue();
        if (v != null) sb.append(v);
      }
    }
    return sb.toString();
  }

  public static String getText(NodeList nl)
  {
    if (nl.getLength() > 0) return getText(nl.item(0));
    return "";
  }

  public static String formatPrice(NodeList nl)
  {
    return getText(nl).trim();
  }

  public static String formatPrice(String value)
  {
    String result = processMyFormatting(value);
    return result;
  }



}

In order to make XSL simple I added to Java class another method formatPrice(NodeList nl). This method allows to call java extension as <xsl:value-of select="sample:formatPrice(.)"/>. In this case price parameter is a NodeList and we have to get the text value from first child node. Couple simple methods “getText” help us to do it.


Thanks a lot if you are reached here. We plan to put on our web site in a nearest future more information about simple way of working with XSL, with examples of included templates, using Java extensions, working with DOM, multi-XSL transformations, etc. Visit our web site at http://www.softcorporation.com.

Vadim L Permyakov.
SoftCorporation LLC.



Home

Keywords: XML, XSL, XSLT, XSL transformations, e-Business, SoftCorporation LLC.