這篇技巧文章使用 Apache Project 的 Xalan Java 2 轉換引擎及其實現(請參閱 參考資料)。總體概念對於任何實現都是相同的,XSLT 建議書並未要求任何特殊實現方法。除了 Xalan,在您的 CLASSPATH
上包含還需要 js.jar 檔案(參閱 參考資料),它包含了 JavaScript 實現,還需要 bsf.jar
檔案,它是 Xalan 發行版的一部分。
來源文件
樣式表文檔樣本記載了猜數遊戲中的項,其中猜數者從 1 到 100 猜三個數。樣式表擷取這三個數並將它們與隨機數進行比較。樣本文檔含有兩組猜測數:
樣本文檔
<?xml version="1.0"?> <entries gameID="DWO"> <entry> <player>John</player> <guess>3</guess> <guess>9</guess> <guess>222</guess> </entry> <entry> <player>Mary</player> <guess>88</guess> <guess>76</guess> <guess>5</guess> </entry> </entries>
|
建立組件
使用擴充元素或函數的第一步是定義要執行的代碼。這涉及為代碼定義新的名稱空間及容器:
基本樣式表
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lxslt="http://xml.apache.org/xslt"
xmlns:result="http://www.example.com/results"
extension-element-prefixes="result"
version="1.0">
<lxslt:component prefix="result" elements="rules" functions="getResult">
<lxslt:script lang="javascript">
function getResult (thisGuess) {
var thisResult = parseInt(Math.random()*100);
if (thisResult == parseInt(thisGuess)) {
return "Correct!";
} else {
return "Wrong! The actual answer was "+thisResult+
", not "+thisGuess+".";
}
}
</lxslt:script>
</lxslt:component>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
表面上,這是一個添加了兩個新名稱空間的典型樣式表。第一個名稱空間的首碼是 lxslt
,告訴處理器哪個元素定義了新功能。第二個名稱空間的首碼是 result
,表明對新功能的一次調用。最後, extension-element-prefixes
屬性讓處理器知道哪個元素作為正常流的一部分不該被轉換。(如同我們將看到的一樣,它們仍然會返回一個值作為輸出。)
組件本身指定從 result
名稱空間首碼調用其內部的所有代碼。它也讓處理器知道哪些函數將從擴充元素調用,以及哪些函數將從擴充函數調用。指令碼元素描述函數本身。
在這個例子中,我們從一個函數開始,該函數擷取一個參數並將它與 1 到 100 間的隨機數進行比較,返回一個表示結果的字串。
擴充函數
在 XSLT 樣式表中,擴充函數實際擴充 XPath,因此,您可以像使用內建函數(如 translate()
或 round()
)一樣使用它們。
調用函數
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="entry">
Guesser: <xsl:value-of select="player"/>
<xsl:apply-templates select="guess"/>
</xsl:template>
<xsl:template match="guess">
Guess: <xsl:value-of select="."/>
Actual: <xsl:value-of select="result:getResult(string(.))"/>
</xsl:template>
</xsl:stylesheet>
本樣本將當前節點( guess
)的字串值傳遞給 getResult()
函數。名稱空間讓處理器知道觸發結果組件中的函數。
圖 1. 初步結果
使用元素
擴充元素比函數要複雜一點。我們不希望擴充元素簡單地返回一個值(雖然它們可以這樣做),而希望它們在樣式表處理過程中的特定“時刻”執行某個特定的操作。也不希望獲得一個隨機的參數列表(因為擴充函數也可以),擴充元素背後的代碼含有兩個良好定義的參數。
rules
元素觸發 rules()
函數的處理。該函數將 rules
元素本身( elem
)作為其參數之一,允許您檢索它擁有的任何定製屬性的值。
使用處理器上下文
擴充元素最強大的方面可能是通過 XSL 處理器上下文參數訪問來源文件本身的能力。
處理器上下文
<lxslt:component prefix="result" elements="rules" functions="getResult">
<lxslt:script lang="javascript">
function rules(ctx, elem) {
ctxNode = ctx.getContextNode();
gameID = ctxNode.getFirstChild().getAttribute("gameID");
return "Contest "+gameID+" is based on "+
elem.getAttribute("guessType")+" guesses.";
}
</lxslt:script>
</lxslt:component>
rules
函數的第一個參數是 org.apache.xalan.extensions.XSLProcessorContext
對象形式的處理器上下文。這允許您檢索代表上下文節點、整個源樹、樣式表以及當前執行轉換的轉換程式的對象。訪問上下文節點是最常見的。一旦由 getContextNode()
方法返回,這就是一個可以使用典型 DOM 操作的典型 XML 節點。
圖 2. 最終輸出
原文地址:http://www.ibm.com/developerworks/cn/xml/tips/x-tipxsltjs/index.html