Monday, November 25, 2013

Using JAXB With XSLT to Produce HTML

JAXB (JSR-222) enables Java to treat a domain model as XML.  In this post I will demonstrate how to leverage this by applying an XSLT stylesheet to a JAXB model to produce HTML.  This approach is often leveraged when creating JAX-RS applications.

Java Model

Below is the Java model that will be used for this example.  It represents information about a collection of books.

Library
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package blog.jaxbsource.xslt;
 
import java.util.*;
import javax.xml.bind.annotation.*;
 
@XmlRootElement
public class Library {
 
    private List books = new ArrayList();
 
    @XmlElement(name="book")
    public List getBooks() {
        return books;
    }
 
}

Book
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package blog.jaxbsource.xslt;
 
public class Book {
 
    private String title;
    private String author;
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getAuthor() {
        return author;
    }
 
    public void setAuthor(String author) {
        this.author = author;
    }
 
}

XML Structure 

Our JAXB model can be used to produce XML documents that conform to the following XML schema.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
 <xs:element name="library" type="library" />
 
 <xs:complexType name="library">
  <xs:sequence>
   <xs:element name="book" type="book" minOccurs="0"
    maxOccurs="unbounded" />
  </xs:sequence>
 </xs:complexType>
 
 <xs:complexType name="book">
  <xs:sequence>
   <xs:element name="author" type="xs:string" minOccurs="0" />
   <xs:element name="title" type="xs:string" minOccurs="0" />
  </xs:sequence>
 </xs:complexType>
 
</xs:schema>

The above XML schema was produced using the following code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package blog.jaxbsource.xslt;
 
import java.io.IOException;
import javax.xml.bind.*;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
 
public class GenSchema {
 
    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Library.class);
         
        jc.generateSchema(new SchemaOutputResolver() {
 
            @Override
            public Result createOutput(String namespaceURI, String suggestedFileName)
                    throws IOException {
                StreamResult result = new StreamResult(System.out);
                result.setSystemId(suggestedFileName);
                return result;
            }
             
        });
    }
 
}

Stylesheet

Below is the XSLT stylesheet that we will use to convert the XML (JAXB model) to HTML.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
 <xsl:template match="/">
  <html>
   <body>
    <h2>My Library</h2>
    <table>
     <tr>
      <th>Title</th>
      <th>Author</th>
     </tr>
     <xsl:for-each select="library/book">
      <tr>
       <td>
        <xsl:value-of select="title" />
       </td>
       <td>
        <xsl:value-of select="author" />
       </td>
      </tr>
     </xsl:for-each>
    </table>
   </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

Demo Code

In our demo code we will use the standard javax.xml.transform APIs to do the conversion. Our JAXB input is wrapped in an instance of JAXBSource, and the output is wrapped in an instance of StreamResult.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package blog.jaxbsource.xslt;
 
import javax.xml.bind.*;
import javax.xml.bind.util.JAXBSource;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
 
public class Demo {
 
    public static void main(String[] args) throws Exception {
        // XML Data
        Book book1 = new Book();
        book1.setAuthor("Jane Doe");
        book1.setTitle("Some Book");
 
        Book book2 = new Book();
        book2.setAuthor("John Smith");
        book2.setTitle("Another Novel");
         
        Library catalog = new Library();
        catalog.getBooks().add(book1);
        catalog.getBooks().add(book2);
 
        // Create Transformer
        TransformerFactory tf = TransformerFactory.newInstance();
        StreamSource xslt = new StreamSource(
                "src/blog/jaxbsource/xslt/stylesheet.xsl");
        Transformer transformer = tf.newTransformer(xslt);
 
        // Source
        JAXBContext jc = JAXBContext.newInstance(Library.class);
        JAXBSource source = new JAXBSource(jc, catalog);
 
        // Result
        StreamResult result = new StreamResult(System.out);
         
        // Transform
        transformer.transform(source, result);
    }
 
}

Output 

The following HTML output was produced as a result of running the demo code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xml version="1.0" encoding="UTF-8"?>
<html>
 <body>
  <h2>My Library</h2>
  <table>
   <tr>
    <th>Title</th>
    <th>Author</th>
   </tr>
   <tr>
    <td>Some Book</td>
    <td>Jane Doe</td>
   </tr>
   <tr>
    <td>Another Novel</td>
    <td>John Smith</td>
   </tr>
  </table>
 </body>
</html>

Further Reading 

If you found this post interesting then you may also like: 

No comments: