You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
5.1 KiB
195 lines
5.1 KiB
[[mvc-view-xslt]] |
|
= XSLT Views |
|
|
|
XSLT is a transformation language for XML and is popular as a view technology within web |
|
applications. XSLT can be a good choice as a view technology if your application |
|
naturally deals with XML or if your model can easily be converted to XML. The following |
|
section shows how to produce an XML document as model data and have it transformed with |
|
XSLT in a Spring Web MVC application. |
|
|
|
This example is a trivial Spring application that creates a list of words in the |
|
`Controller` and adds them to the model map. The map is returned, along with the view |
|
name of our XSLT view. See xref:web/webmvc/mvc-controller.adoc[Annotated Controllers] for details of Spring Web MVC's |
|
`Controller` interface. The XSLT controller turns the list of words into a simple XML |
|
document ready for transformation. |
|
|
|
|
|
|
|
[[mvc-view-xslt-beandefs]] |
|
== Beans |
|
|
|
Configuration is standard for a simple Spring web application: The MVC configuration |
|
has to define an `XsltViewResolver` bean and regular MVC annotation configuration. |
|
The following example shows how to do so: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
---- |
|
@EnableWebMvc |
|
@ComponentScan |
|
@Configuration |
|
public class WebConfig implements WebMvcConfigurer { |
|
|
|
@Bean |
|
public XsltViewResolver xsltViewResolver() { |
|
XsltViewResolver viewResolver = new XsltViewResolver(); |
|
viewResolver.setPrefix("/WEB-INF/xsl/"); |
|
viewResolver.setSuffix(".xslt"); |
|
return viewResolver; |
|
} |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
---- |
|
@EnableWebMvc |
|
@ComponentScan |
|
@Configuration |
|
class WebConfig : WebMvcConfigurer { |
|
|
|
@Bean |
|
fun xsltViewResolver() = XsltViewResolver().apply { |
|
setPrefix("/WEB-INF/xsl/") |
|
setSuffix(".xslt") |
|
} |
|
} |
|
---- |
|
====== |
|
|
|
|
|
[[mvc-view-xslt-controllercode]] |
|
== Controller |
|
|
|
We also need a Controller that encapsulates our word-generation logic. |
|
|
|
The controller logic is encapsulated in a `@Controller` class, with the |
|
handler method being defined as follows: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
---- |
|
@Controller |
|
public class XsltController { |
|
|
|
@RequestMapping("/") |
|
public String home(Model model) throws Exception { |
|
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); |
|
Element root = document.createElement("wordList"); |
|
|
|
List<String> words = Arrays.asList("Hello", "Spring", "Framework"); |
|
for (String word : words) { |
|
Element wordNode = document.createElement("word"); |
|
Text textNode = document.createTextNode(word); |
|
wordNode.appendChild(textNode); |
|
root.appendChild(wordNode); |
|
} |
|
|
|
model.addAttribute("wordList", root); |
|
return "home"; |
|
} |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
---- |
|
import org.springframework.ui.set |
|
|
|
@Controller |
|
class XsltController { |
|
|
|
@RequestMapping("/") |
|
fun home(model: Model): String { |
|
val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() |
|
val root = document.createElement("wordList") |
|
|
|
val words = listOf("Hello", "Spring", "Framework") |
|
for (word in words) { |
|
val wordNode = document.createElement("word") |
|
val textNode = document.createTextNode(word) |
|
wordNode.appendChild(textNode) |
|
root.appendChild(wordNode) |
|
} |
|
|
|
model["wordList"] = root |
|
return "home" |
|
} |
|
} |
|
---- |
|
====== |
|
|
|
So far, we have only created a DOM document and added it to the Model map. Note that you |
|
can also load an XML file as a `Resource` and use it instead of a custom DOM document. |
|
|
|
There are software packages available that automatically 'domify' |
|
an object graph, but, within Spring, you have complete flexibility to create the DOM |
|
from your model in any way you choose. This prevents the transformation of XML playing |
|
too great a part in the structure of your model data, which is a danger when using tools |
|
to manage the DOMification process. |
|
|
|
|
|
|
|
[[mvc-view-xslt-transforming]] |
|
== Transformation |
|
|
|
Finally, the `XsltViewResolver` resolves the "`home`" XSLT template file and merges the |
|
DOM document into it to generate our view. As shown in the `XsltViewResolver` |
|
configuration, XSLT templates live in the `war` file in the `WEB-INF/xsl` directory |
|
and end with an `xslt` file extension. |
|
|
|
The following example shows an XSLT transform: |
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
---- |
|
<?xml version="1.0" encoding="utf-8"?> |
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
|
|
|
<xsl:output method="html" omit-xml-declaration="yes"/> |
|
|
|
<xsl:template match="/"> |
|
<html> |
|
<head><title>Hello!</title></head> |
|
<body> |
|
<h1>My First Words</h1> |
|
<ul> |
|
<xsl:apply-templates/> |
|
</ul> |
|
</body> |
|
</html> |
|
</xsl:template> |
|
|
|
<xsl:template match="word"> |
|
<li><xsl:value-of select="."/></li> |
|
</xsl:template> |
|
|
|
</xsl:stylesheet> |
|
---- |
|
|
|
The preceding transform is rendered as the following HTML: |
|
|
|
[source,html,indent=0,subs="verbatim,quotes"] |
|
---- |
|
<html> |
|
<head> |
|
<META http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
|
<title>Hello!</title> |
|
</head> |
|
<body> |
|
<h1>My First Words</h1> |
|
<ul> |
|
<li>Hello</li> |
|
<li>Spring</li> |
|
<li>Framework</li> |
|
</ul> |
|
</body> |
|
</html> |
|
----
|
|
|