15.5.XSLT

优质
小牛编辑
134浏览
2023-12-01

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容器也提供了,但要警惕,它可能是一些错误的来源。