In this post I will show you how to convert XML to HTML using XSLT in Java using Saxon HE version 11 library
We will add the dependency to our pom:
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>11.5</version>
</dependency>
Our sample XML will be:
<detail>
<product>
<detail>Socket</detail>
<brand>GM</brand>
<models>
<model>
<model-no>123</model-no>
<model-notes>Test</model-notes>
</model>
<model>
<model-no>34</model-no>
<model-notes>Test 2</model-notes>
</model>
<model>
<model-no>56</model-no>
<model-notes>Test 3</model-notes>
</model>
<model>
<model-no>23</model-no>
<model-notes>Test 4</model-notes>
</model>
</models>
</product>
<manufacturer>
<country>
<code>IN</code>
<name>India</name>
</country>
<name>Philips Industries Ltd</name>
</manufacturer>
</detail>
The XSLT we will be using to convert the XML into HTML is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="detail">
<div class="row">
<div class="col">
<h3>Details</h3>
<form class="form-view">
<div class="form-group row">
<label for="" class="col-12 col-sm-4 col-lg-3 col-xl-2 col-form-label">Brand</label>
<div class="col-12 col-sm-8 col-lg-3 col-xl-4">
<span class="label-value"> <xsl:value-of select="product/brand" /> </span>
</div>
</div>
<div class="form-group row">
<label for="" class="col-12 col-sm-4 col-lg-3 col-xl-2 col-form-label">Product</label>
<div class="col-12 col-sm-8 col-lg-3 col-xl-4">
<span class="label-value"><xsl:value-of select="product/detail" /> </span>
</div>
</div>
<div class="form-group row">
<label for="" class="col-12 col-sm-4 col-lg-3 col-xl-2 col-form-label">Manufacturer</label>
<div class="col-12 col-sm-8 col-lg-3 col-xl-4">
<span class="label-value"><xsl:value-of select="manufacturer/name" /> </span>
</div>
<label for="" class="col-12 col-sm-4 col-lg-3 col-xl-2 col-form-label">Manufactured In</label>
<div class="col-12 col-sm-8 col-lg-3 col-xl-4">
<span class="label-value">
<xsl:value-of select="manufacturer/country/name" />
</span>
</div>
</div>
</form><!-- End of .form-view -->
<h3>Models</h3>
<div class="table-responsive">
<table class="table table-hover" border="0" cellpadding="0" cellspacing="0">
<thead v-once="">
<tr>
<th width="30%">Model Number</th>
<th width="70%">Notes</th>
</tr>
</thead>
<tbody>
<xsl:for-each select="product/models/model">
<tr>
<td data-label="Model Number"><xsl:value-of select="model-no" /> </td>
<td data-label="Notes"><xsl:value-of select="model-notes" /> </td>
</tr>
</xsl:for-each>
</tbody>
</table>
</div>
</div><!-- End of .col -->
</div><!-- End of .row -->
</xsl:template><!-- detail template -->
<xsl:template match="/">
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>XML to HTML</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
crossorigin="anonymous" />
</head>
<body>
<div class="container">
<xsl:apply-templates />
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
crossorigin="anonymous"></script>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Following are the steps to process the XML to HTML using Saxon library:
1. Create a new Processor
instance. We are passing false
because we are using the free edition of the library
Processor processor = new Processor(false);
2. Create a new Xslt30Transformer
by loading the XSLT template to be used:
XsltCompiler xsltCompiler = processor.newXsltCompiler();
InputStream xsltStream = ClassLoader.getSystemResourceAsStream("sample-xslt2.xsl");
XsltExecutable xsltExecutable = xsltCompiler.compile(new StreamSource(xsltStream));
Xslt30Transformer xsltTransformer30 = xsltExecutable.load30();
In the above code we have placed our sample-xslt2.xsl
at the root of the classpath. In our case it is the src/main/resources folder.
There are two XSLT transformers available:
XsltTransformer
which is based on XSLT 2.0Xslt30Transformer
which is based on XSLT 3.0
Both of them have some differences at the XSLT W3C specification as well as some differences at the API level in the way we set the source XML and destination for HTML. We can get the XSLT 2.0 based transformer by invoking the method load()
as shown below:
XsltTransformer xsltTransformer = xsltExecutable.load();
3. Initialize the destination for the XSLT transformer output:
We can write the output of the transformation to a file or to an output stream or to another XSLT Transformer. In our case we will write to a ByteArrayOutputStream
. The place to which we write the output of the transformation is called as Destination
here. So there are different imeplementations of Destination
provided by the library and the one we will be using is called Serializer
If you are using Xslt30Transformer
then you can create a new Serializer
as shown below:
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
Serializer byteArrayOutput = xsltTransformer30.newSerializer(arrayOutputStream);
Or if you are using XsltTransformer
then you can create a new Serializer
using the Processor
instance as shown below:
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
Serializer byteArrayOutput = processor.newSerializer(arrayOutputStream);
We will set some preferences for the output via the properties on the Serializer
byteArrayOutput.setOutputProperty(Serializer.Property.INDENT, "yes");
byteArrayOutput.setOutputProperty(Serializer.Property.METHOD, "html");
byteArrayOutput.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
4. Initialize the source XML to be processed
We will create an instance of StreamSource
and point it to the input stream of the XML to be processed as shown below:
StreamSource streamSource = new StreamSource(ClassLoader.<em>getSystemResourceAsStream</em>("sample-xml2.xml"));
Finnally we invoke the transform()
method of the Xslt30Transformer
to process the XML and print out the contents from the ByteArrayOutputStream
as shown below:
xsltTransformer30.transform(streamSource, byteArrayOutput);
System.out.println(arrayOutputStream.toString());
If you are using the XSLT 2.0 transformer i.e XsltTransformer
then you need to set the source and destination and then invoke the transform()
method as shown below:
xsltTransformer.setSource(streamSource);
xsltTransformer.setDestination(byteArrayOutput);
xsltTransformer.transform();
The HTML generated from this looks something like below:
Below is the complete code for processing based on Xslt30Transformer
. You can also find the working code in the Github repo here.
public class App
{
public static void main( String[] args ) throws SaxonApiException, FileNotFoundException {
Processor processor = new Processor(false);
XsltCompiler xsltCompiler = processor.newXsltCompiler();
InputStream xsltStream = ClassLoader.getSystemResourceAsStream("sample-xslt2.xsl");
XsltExecutable xsltExecutable = xsltCompiler.compile(new StreamSource(xsltStream));
Xslt30Transformer xsltTransformer30 = xsltExecutable.load30();
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
Serializer byteArrayOutput = processor.newSerializer(arrayOutputStream);
byteArrayOutput.setOutputProperty(Serializer.Property.INDENT, "yes");
byteArrayOutput.setOutputProperty(Serializer.Property.METHOD, "html");
byteArrayOutput.setOutputProperty(Serializer.Property.OMIT_XML_DECLARATION, "yes");
StreamSource streamSource = new StreamSource(
ClassLoader.getSystemResourceAsStream("sample-xml2.xml"));
xsltTransformer30.transform(streamSource, byteArrayOutput);
System.out.println(arrayOutputStream.toString());
}
}
The post Convert XML to HTML using XSLT in Java appeared first on Experiences Unlimited.