15.5.XSLT
15.5. XSLT
XSLT是一种用于XML的转换语言,并作为一种在web应用中使用的view层技术广为人知。 如果你的应用本来就要处理XML,或者模型数据可以很容易转化为XML,那么XSLT是一个很好的选择。 下面的内容展示了在一个Spring应用中如何生成XML格式的模型数据,并用XSLT进行转换。
15.5.1. 写在段首
这是一个很小的Spring应用的例子,它只是在Controller中创建一个词语列表,并将它们加至模型数据(model map)。 模型数据和我们的XSLT视图名一块儿返回。 参考 第 14.3 节 “控制器” 获得Spring Controller
的细节。 XSLT视图把词语列表转化为一段简单XML,等待后续转换。
15.5.1.1. Bean 定义
这是一个简单的Spring应用的标准配置。dispatcher servlet配置文件包含一个指向 ViewResolver
的引用、URL映射和一个简单的实现了我们的词语生成逻辑的controller bean:
<bean id="homeController"class="xslt.HomeController"/>
它实现了我们的词语生成“逻辑”。
15.5.1.2. 标准MVC控制器代码
控制器逻辑封装在一个AbstractController的子类,它的handler方法定义如下:
protected ModelAndView handleRequestInternal( HttpServletRequest req, HttpServletResponse resp) throws Exception { Map map = new HashMap(); List wordList = new ArrayList(); wordList.add("hello"); wordList.add("world"); map.put("wordList", wordList); return new ModelAndView("home", map); }
到目前为止,我们还没有做什么特定于XSLT的事情。在任何一种Spring MVC应用中,模型数据都以同样的方式被创建。 现在根据应用的配置,词语列表可以作为请求属性加入从而被JSP/JSTL渲染,或者通过加入VelocityContext来被Velocity处理。 为了使用XSLT渲染它们,应该以某种方式把它们转化为XML文档。有些软件包能自动完成对象图到XML文档对象模型的转化。 但在Spring中,你有完全的自由度,能以任何方式完成从模型数据到XML的转化。 这可以防止XML转化部分在你的模型结构中占据太大的比重,使用额外工具来管理转化过程是一种风险。
15.5.1.3. 把模型数据转化为XML
为了从词语列表或任何其他模型数据创建XML文档,我们创建一个 org.springframework.web.servlet.view.xslt.AbstractXsltView
的子类, 并实现抽象方法 createDomNode()
。其第一个参数即model Map。 下面是我们这个小应用中HomePage类的完整代码——它用了JDOM来生成XML文档,然后再转化为W3C节点。这样挺简单,因为我发现JDOM(或DOM4J)的API比W3C的API好用。
package xslt; // imports omitted for brevity public class HomePage extends AbstractXsltView { protected Node createDomNode( Map model, String rootName, HttpServletRequest req, HttpServletResponse res ) throws Exception { org.jdom.Document doc = new org.jdom.Document(); Element root = new Element(rootName); doc.setRootElement(root); List words = (List) model.get("wordList"); for (Iterator it = words.iterator(); it.hasNext();) { String nextWord = (String) it.next(); Element e = new Element("word"); e.setText(nextWord); root.addContent(e); } // convert JDOM doc to a W3C Node and return return new DOMOutputter().output( doc ); } }
15.5.1.3.1. 添加stylesheet参数
你可以在上述子类中定义一些传给转化对象的参数,它们由健值对(name/value pairs)构成, 其中参数名必须与XSLT模板中定义的 <xsl:param name="myParam">defaultValue</xsl:param>
一致。 为了指定这些参数,你需要覆写继承自AbstractXsltView的 getParameters()
方法并返回一个包含健值对的Map
。 如果你需要从当前请求中获取信息,你可以选择覆写 getParameters(HttpServletRequest request)
方法(从Spring 1.1版本以后)。
15.5.1.3.2. 格式化日期和货币
比起JSTL和Velocity,XSLT对本地货币和日期格式的支持相对较弱。 基于这点,Spring提供了一个辅助类,你可以在 createDomNode()
方法中调用它来获得这样的支持。 请参考 org.springframework.web.servlet.view.xslt.FormatHelper
类的Javadoc。
15.5.1.4. 定义视图属性
对于“写在段首”中的只有一个视图的情况来说,views.properties文件(或者等价的xml文件,如果你用一种基于XML的视图解析器的话,就像在上面的Velocity例子中)看起来是这样的:
home.class=xslt.HomePage home.stylesheetLocation=/WEB-INF/xsl/home.xslt home.root=words
这里你可以看到,第一个属性'.class'指定了视图类,即我们的HomePage,其中完成从模型数据到XML文档的转化。 第二个属性stylesheetLocation显式指定了XSLT文件的位置,它用于完成从XML到HTML的转化。 最后一个属性'.root'指定了用作XML文档根元素的名字,它被作为 createDomNode
方法的第二个参数传给HomePage类。
15.5.1.5. 文档转换
最后,我们有一段转换上述文档的XSLT代码。 正如在view.properties中看到的,它被命名为 home.xslt
,存放在war文件中的 WEB-INF/xsl
下。
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text/html" omit-xml-declaration="yes"/> <xsl:template match="/"> <html> <head><title>Hello!</title></head> <body> <h1>My First Words</h1> <xsl:for-each select="wordList/word"> <xsl:value-of select="."/><br /> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet>
15.5.2. 小结
下面是一个简化的WAR目录结构,其中总结了上面提到的文件和它们在WAR中的位置:
ProjectRoot | +- WebContent | +- WEB-INF | +- classes | | | +- xslt | | | | | +- HomePageController.class | | +- HomePage.class | | | +- views.properties | +- lib | | | +- spring.jar | +- xsl | | | +- home.xslt | +- frontcontroller-servlet.xml
你要确保classpath下存在XML解析器和XSLT引擎。JDK1.4默认已提供了这些,多数J2EE容器也提供了,但要警惕,它可能是一些错误的来源。