PART-3
XSLT
PROCESSING USING XALAN IN JAVA
R.S.RAMASWAMY
rs.ramaswamy.gmail.com
In this third part of the
tutorial on XSLT IN ASP.Net & J2EE, we
the favourite XSLT processor of the Java World, namely Apache-Xalan. We
will illustrate the various methods using xalan-1 & xalan-2 and also
explains the TrAX API in jaxp1.1 in jdk1.4 as applied in console programs,
servlet and also JSP.
The following table
shows the various xslt processors.
Processor |
Language |
From |
XT |
Java |
James Clark |
Xalan |
C++ and Java |
IBM/Apache |
Oracle XSLT |
C++ and Java |
Oracle |
Saxon |
Java |
Michael Kay |
MSXML |
C++ |
Microsoft |
XML::XSLT |
Perl |
SourceForge |
XALAN
, was previously known as LotusXSL and
was originally developed in IBM labs under the leadership of Scott
Boag. Later, it was handed over to Apache Foundation for
further development as an open source project. At that time , it was known as
xalan-1.
Subsequently, there have been a number of changes and the current version is xalan-2.
Many books, published about 5 years back,
(around 1999),refer to xalan and xerces
and give code examples. Unfortunately, much of the code examples , will neither
compile nor run, unless the xalan
version-1 is used along with the corresponding xerces
processor. Therefore, we will see a simple example using xalan-1 first and then
changeover to xalan-2 given in jdk1.4. We are using xalan1.0
and corresponding xerces. As we do not want to use the latest xalan (ie)
version2, available in jaxp1.1 of jdk1.4, we will give path to
d:\jdk1.3\bin only.
We may be unable to get xalan1.0 , from the web now!
We can get it from the CD associated with 'Applied XML Solutions ' by a famous
& brilliant author 'Benoit Marchal'( Techmedia pub).The same version
is referred to by another famous book 'XML Development with Java2' by Michael
Daconta(Techmedia).
First and foremost ,
install xalanj as xalan1 in
C:\ drive .We can find a number of very valuable jar files in this
folder.
a) xalan.jar
b) xerces.jar
c) bsf.jar
( bean scripting framework)
d) bsfengines.jar
And also a lot of useful documents and references.
---------------------------------------
We begin by editing
' g:\xslt\xsltester.java'
// g:\xslt\xsltester.java
import org.apache.xalan.xslt.*;
class xsltester
{
public static void main(String
args[])
{
try
{
XSLTProcessor processor=
XSLTProcessorFactory.getProcessor();
XSLTInputSource a=
new
XSLTInputSource("students.xml");
XSLTInputSource b=
new
XSLTInputSource("xsl1.xsl");
XSLTResultTarget c=
new
XSLTResultTarget("result.htm");
processor.process(a,b,c);
System.out.println(“Output ready!see result.htm");
} catch(Exception e1)
{ System.out.println(""+e1); }
}
}
----------------------------------------------------------
The class-nomenclature is
absolutely streamlined and intuitive.
g:\xslt>set
path=
c:\windows\command;d:\jdk1.3\bin
g:\xslt>set
classpath=
g:\xslt;c:\xalan1\xalan.jar;
c:\xalan1\xerces.jar
Now we are ready to compile .
>javac
xsltester.java // compile
It will compile without
hitch.
Now place students.xml & xsl1.xsl in
g:\xslt folder and execute the program.
>java
xsltester // execute
We will get the message:
'output ready!..see
result.htm'
we can check up by seeing result.htm!
**********************************************************
That was about getting the transformation done by a Java program.
But, We can also get the same result
without writing any java code,
from command line.
>java org.apache.xalan.xslt.Process
-in students.xml
-xsl xsl1.xsl > result.htm
( to be typed continuously)
we
get the following messages:
parsing xsl1.xsl
.....219
milli-seconds
parsing students.xml
....31 ,,
transforming ...............16 ,,
Is it not super-fast?
We can now see result.htm
in console or in browser.KINDLY NOTE THAT THE ABOVE CODE WILL NOT WORK WITH XALAN2 IN
JAXP1.1 OF JDK1.4
We now see how we can use jdk1.4 for
transformations.
we begin by using xalan2 in jdk1.4
All that we have to do is
to type the following command
( assuming that we have
already done the following:
set
path=c:\windows\command;d:\jdk1.4\bin
Remember to place students.xml & xsl1.xsl in the current folder).
>java org.apache.xalan.xslt.Process
-in students.xml
-xsl xsl1.xsl
-out traxout.htm
( the command should be
typed in a single line)
After this we can verify
traxout.htm
-----------------------------------------------
xalan2
xslt processor is built into jaxp1.1 and jdk1.4
incorporates jaxp1.1. We can see
traxout.htm in browser .( Towards the end of this tutorial, we will be
referring to the super-fast and easy method of testing the transformation., So
kindly make a special note.)
When we want programmatic
execution, we can use a program as follows:
// console mode java
//
g:/trax/traxbeanconsole.java
import
java.io.*;
import
javax.xml.transform.*;
import
javax.xml.transform.stream.*;
// set path=c:\windows\command;d:\jdk1.4\bin
// set classpath=<current
folder>( g:\trax)
class
traxbeanconsole
{
public static void main(String args[])
{
traxbean bean1 = new traxbean();
String
a = args[0]; // xsl file
String
b = args[1]; // xml file
String
c = args[2]; // output file
bean1.doTrax(a,b,c);
}
}
//-------------------------------------------------
class
traxbean // user -defined class
{
traxbean()
{
}
public
void doTrax
(String a, String b, String c)
{
try
{
TransformerFactory factory=
TransformerFactory.newInstance();
StreamSource xsl=
new StreamSource(a);
Transformer transformer=
factory.newTransformer(xsl);
StreamSource xml= new
StreamSource(b);
StreamResult result= new
StreamResult(c);
transformer.transform(xml,result);
System.out.println("result sent to
traxdemo.htm");
System.out.println("try 'type
traxdemo.htm' ");
}catch(Exception e1) { System.out.println(""+e1); }
}// function
}//
inner class
===============================================
The
console mode example given above will work only in jdk1.4, which incorporates
JAXP1.1 , with built in support for TrAX API and Namespaces. Unlike xalan-1 , we
don't have to give classpath.
Let
us create this file in
g:\trax\traxbeandemo.java
>set path=c:\windows\command;d:\jdk1.4\bin
We will
be able to compile.
Run the program as,
> java traxbeanconsole
xsl1.xsl students.xml result.htm
we get message as :
>result sent to
result.htm
try 'type result.htm'
-------------------------------------------
Explanation for the code follows.
The main program simply creates an instance
of the traxbean class and invokes the bean's method 'doTrax' with three
parameters , namely, xslfile,xmlfile and outputfile.
The
bean's code begins with the creation of TransformerFactory
instance. This is the common pattern in
all the JAXP programs. The Transformer instance is to be created next
but it takes the xsl file as a parameter.
So, we have to define it first. The xsl may come from a
StreamSource or DomSource or SaxSource.For simplicity, we assume a StreamSource.
Now, we create the instance of Transformer.
After this, we can ask
the transformer to transform, but we
have to give two parameters when invoking this command. First parameter is the
StreamSource of the XML file to be transformed and the second parameter is
the StreamResult specifying the
name of the output file. Finally, we invoke the transform command
on the transform object. It 'cannot get
any simpler'.
-----------------------------------------------
If
you get the message that there is no class 'traxbeandemo', set
classpath=g:\trax and try again. Let us now see how we can modify the program
to be used as a servlet.
------------------------------------------------
Create the file as
g:\xslt\traxdemoservlet.java
import
java.io.*;
import
java.net.*;
import
javax.xml.transform.*;
import
javax.xml.transform.stream.*;
import
javax.servlet.*;
import
javax.servlet.http.*;
public
class traxdemoservlet
extends HttpServlet
{
public void doPost
(HttpServletRequest request,
HttpServletResponse response)
throws
IOException,ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String
a = request.getParameter("text1");
String
b = request.getParameter("text2");
a="http://localhost:8080/"+a;
b="http://localhost:8080/"+b;
traxbean bean1 = new traxbean();
String v= bean1.doTrax(a,b);
out.println(v); // send it to browser
}
//-------inner class follows----------
class traxbean
{
traxbean() {
} // constructor
public String doTrax(String a, String b)
{
String r = "";
try
{
TransformerFactory factory=
TransformerFactory.newInstance();
StreamSource xsl=new
StreamSource(a);
//
'http://localhost:8080/xsl1.xsl'
Transformer transformer=
factory.newTransformer(xsl);
StreamSource xml= new StreamSource( b);
//("http://localhost:8080/students.xml");
StreamResult result=
new StreamResult ("g://traxdemo.htm");
transformer.transform(xml,result);
FileInputStream fis=
new
FileInputStream("g://traxdemo.htm");
DataInputStream ins=new DataInputStream(fis);
String s=ins.readLine();
while(s
!= null )
{
r = r+s+"<br>";
s=ins.readLine();
}
}catch(Exception e1) { System.out.println(""+e1);}
return
r;
}
// ================ inner class over =========
}
===============================================
To
compile the above servlet file, we have to set
correct path & classpath:
g:\xslt>
set path=c:\windows\command;d:\jdk1.4\bin
set classpath=e:\tomcat32\lib\servlet.jar
Now, we will be able to
compile.
After compiling, we copy
the servlet's classfile to:
'e:\tomcat32\webapps\root\web-inf\classes'
Remember to copy the
classfile of the servlet's inner-class also.
'traxdemoservlet$traxbean.class'
This is very important.
( Also, remember that
tomcat should be restarted, if any new servlet class is placed or
modified).
Place 'students.xml' and 'xsl1.xsl' in :
'e:\tomcat32\webapps\root'
folder.
It will be noticed that the location of xml file and xsl file is
given as:
"http://localhost:8080/students.xml"
and
"http://localhost:8080/xsl1.xsl"
in the servlet.
But the output file is hard-coded in simple
windows style.
The output file is read by
FileInputStream and each line is sent to the browser.
We place the calling html
file in root folder oftomcat.
Type data as 'xsl1.xsl' in text1 & 'students.xml' in text2 and submit.
In PART4 we will see XSLT in JSP.