?
? ????? PHP ??? ???? ??? ?? ??
XSLT是一種用于XML的轉(zhuǎn)換語言,并作為一種在web應(yīng)用中使用的view層技術(shù)廣為人知。 如果你的應(yīng)用本來就要處理XML,或者模型數(shù)據(jù)可以很容易轉(zhuǎn)化為XML,那么XSLT是一個(gè)很好的選擇。 下面的內(nèi)容展示了在一個(gè)Spring MVC 應(yīng)用中如何生成XML格式的模型數(shù)據(jù),并用XSLT進(jìn)行轉(zhuǎn)換。
這是一個(gè)很小的Spring應(yīng)用的例子,它只是在
Controller
中創(chuàng)建一個(gè)詞語列表,并將它們加至模型數(shù)據(jù)(model map)。模型數(shù)據(jù)和我們的XSLT視圖名一同返回。
請參考第?13.3?節(jié) “控制器”
中關(guān)于Spring MVCController
接口的細(xì)節(jié)。XSLT視圖把詞語列表轉(zhuǎn)化為一段簡單XML,等待后續(xù)轉(zhuǎn)換。
這是一個(gè)簡單的Spring應(yīng)用的標(biāo)準(zhǔn)配置。dispatcher servlet配置文件包含一個(gè)指向
ViewResolver
的引用、URL映射和一個(gè)簡單的實(shí)現(xiàn)了我們的詞語生成邏輯的controller bean:
<bean id="homeController"class="xslt.HomeController"/>
它實(shí)現(xiàn)了我們的詞語生成“邏輯”。
控制器邏輯封裝在一個(gè)AbstractController
的子類,它的handler方法定義如下:
protected ModelAndView handleRequestInternal( HttpServletRequest request, HttpServletResponse response) 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應(yīng)用中,模型數(shù)據(jù)都以同樣的方式被創(chuàng)建。
現(xiàn)在根據(jù)應(yīng)用的配置,詞語列表可以作為請求屬性加入從而被JSP/JSTL渲染,或者通過加入
VelocityContext
來被Velocity處理。
為了使用XSLT渲染它們,應(yīng)該以某種方式把它們轉(zhuǎn)化為XML文檔。有些軟件包能自動(dòng)完成對象圖到XML文檔對象模型的轉(zhuǎn)化。
但在Spring中,你有完全的自由度,能以任何方式完成從模型數(shù)據(jù)到XML的轉(zhuǎn)化。
這可以防止XML轉(zhuǎn)化部分在你的模型結(jié)構(gòu)中占據(jù)太大的比重,使用額外工具來管理轉(zhuǎn)化過程是一種風(fēng)險(xiǎn)。
為了從詞語列表或任何其他模型數(shù)據(jù)創(chuàng)建XML文檔,我們必須創(chuàng)建一個(gè)
org.springframework.web.servlet.view.xslt.AbstractXsltView
的子類, 通常我們也必須實(shí)現(xiàn)抽象方法
createXsltSource(..)
s。其第一個(gè)參數(shù)即model Map。 下面是我們這個(gè)小應(yīng)用中
HomePage
類的完整代碼:
package xslt;
// imports omitted for brevity
public class HomePage extends AbstractXsltView {
protected Source createXsltSource(Map model, String rootName, HttpServletRequest
request, HttpServletResponse response) throws Exception {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = document.createElement(rootName);
List words = (List) model.get("wordList");
for (Iterator it = words.iterator(); it.hasNext();) {
String nextWord = (String) it.next();
Element wordNode = document.createElement("word");
Text textNode = document.createTextNode(nextWord);
wordNode.appendChild(textNode);
root.appendChild(wordNode);
}
return new DOMSource(root);
}
}
你可以在上述子類中定義一些傳給轉(zhuǎn)化對象的參數(shù),它們由健值對(name/value pairs)構(gòu)成,
其中參數(shù)名必須與XSLT模板中定義的
<xsl:param
name="myParam">defaultValue</xsl:param>
一致。 為了指定這些參數(shù),你需要覆寫繼承自
AbstractXsltView
的getParameters()
方法并返回一個(gè)包含健值對的
Map
。 如果你需要從當(dāng)前請求中獲取信息,你可以選擇覆寫
getParameters(HttpServletRequest request)
方法。(這個(gè)方法只有Spring 1.1以后的版本才支持。)
比起JSTL和Velocity,XSLT對本地貨幣和日期格式的支持相對較弱。
基于這點(diǎn),Spring提供了一個(gè)輔助類,你可以在
createXsltSource(..)
方法中調(diào)用它來獲得這樣的支持。 請參考
org.springframework.web.servlet.view.xslt.FormatHelper
類的Javadoc。
對于“寫在段首”中的只有一個(gè)視圖的情況來說,views.properties文件(或者等價(jià)的xml文件,如果你用一種基于XML的視圖解析器的話,就像在上面的Velocity例子中)看起來是這樣的:
home.class=xslt.HomePage home.stylesheetLocation=/WEB-INF/xsl/home.xslt home.root=words
這里你可以看到,第一個(gè)屬性
'.class'
指定了視圖類,即我們的HomePage
,其中完成從模型數(shù)據(jù)到XML文檔的轉(zhuǎn)化。 第二個(gè)屬性
'stylesheetLocation'
指定了XSLT文件的位置,它用于完成從XML到HTML的轉(zhuǎn)化。 最后一個(gè)屬性
'.root'
指定了用作XML文檔根元素的名字,它被作為
createXsltSource(..)
方法的第二個(gè)參數(shù)傳給HomePage
類。
最后,我們有一段轉(zhuǎn)換上述文檔的XSLT代碼。 正如在
'views.properties'
中看到的,它被命名為
'home.xslt'
,存放在war文件中的
'WEB-INF/xsl'
目錄下。
<?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> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="word"> <xsl:value-of select="."/><br/> </xsl:template> </xsl:stylesheet>
下面是一個(gè)簡化的WAR目錄結(jié)構(gòu),其中總結(jié)了上面提到的文件和它們在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默認(rèn)已提供了這些,多數(shù)J2EE容器也提供,但還是要警惕,它可能是一些錯(cuò)誤的根源。