javascript快速入門27--XSLT基礎

水之原發表於2013-12-04

XSL 與 XSLT

XSL 指擴充套件樣式表語言(EXtensible Stylesheet Language)。它主要被用來對XML文件進行格式化,與CSS不同,XSL不僅僅是樣式表語言XSL主要包括三個部分:

  • XSLT 一種用於轉換 XML 文件的語言。 它可以將一個XML檔案轉換成另一種格式的XML檔案或XHTML檔案.
  • XPath 一種用於在 XML 文件中導航,定位元素的語言。
  • XSL-FO , 可擴充套件樣式表語言格式化物件(Extensible Stylesheet Language Formatting Objects) ,用於格式化供輸出的 XML 資料。XSL-FO 目前通常被稱為 XSL (儘管這算是一種誤解,但這樣說是可以的,因為在格式化XML方面,XSL-FO起著和CSS一樣的作用!)

XSLT 指 XSL 轉換(XSL Transformations)。 它是 XSL 中最重要的部分。通過 XSLT,您可以向或者從輸出檔案新增或移除元素和屬性。您也可重新排列元素,執行測試並決定隱藏或顯示哪個元素,等等。描述轉化過程的一種通常的說法是,XSLT 把 XML 源樹轉換為 XML 結果樹。

書寫 XSLT

XSLT 檔案本身也是XML 檔案,一般 以.xml .xsl .xslt幾種檔案字尾名儲存.XSLT遵循XML的語法,檔案開頭一般都加有XML宣告,XML宣告之後是文件根元素stylesheet或transform(兩者之一),並且使用version屬性宣告XSLT版本,目前版本是1.0,2.0還在草案中,XSLT的所有內建元素都從屬於"http://www.w3.org/1999/XSL/Transform"名稱空間,所以應該在文件根元素上宣告一個xsl或xs的名稱空間!

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" />    

 

上面建立了一個最基本的XSLT檔案,將其應用於任何XML文件,在支援XSLT的瀏覽器開啟該XML文件,會看到所有的文件顯示了出來,而標籤沒有了!事實上,在瀏覽器中真正顯示的是HTML,XSLT將XML轉換成了HTML.我們可以更進一步指定轉換成HTML的版本,比如轉換成XHTML!

    <?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" encoding="utf-8"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" />
    </xsl:stylesheet>

 

output元素定義輸出文件的格式。method屬性可接受xml,html,text,name四種格式;version設定輸出格式的 W3C 版本號(僅在 method="html" 或 method="xml" 時使用); encoding設定輸出中編碼屬性的值(對於HTML將會輸出成charset的值); doctype-public規定 DTD 中要使用的公共識別符號; doctype-system規定 DTD 中要使用的系統識別符號; indent 規定在輸出結果樹時是否要增加空白,該值必須為 yes 或 no。

template 模版

可以用template來定義模版.template元素必須有match或name兩個屬性之一或兩者都有,match屬性用以並聯XML中的元素,其值為一個XPath表示式,XPath表示式所選取的元素會被應用模版而進行轉換. name屬性為模版定義名稱,用以在其它地方引用.一個template元素裡面包含的是一些將被輸出的HTML或XML標籤.

    <?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" version="1.0" encoding="UTF-8" indent="yes"/>
        <xsl:template match="/bank/p/name">
            <strong>Name</strong>
        </xsl:template>
    </xsl:stylesheet>

 

對於使用一個沒有任何模版的XSLT的XML檔案,在瀏覽器中顯示時只是簡單的將其中的文字顯示出來,應用了上面的XSLT之後,根元素bank下面子元素p的子元素name的值都將會顯示成一個加粗的Name!而其它的則只是普通的文字.但這樣並沒有什麼意義,我們還可以更進一步,將被XPath表示式"/bank/p/name"選取的元素的值顯示出來-------value-of元素!value-of元素的select屬性是必須的,屬性值是一個XPath表示式,指定一個節點(如果是多節點,value-of中會獲取第一個節點的值),然後將其裡面的文字輸出!將上面的模版替換成下面的,輸出後就會將所有的name加粗!

注意,任何正文內容的輸出都應該放在template元素裡面!

    <xsl:template match="/bank/p/name">
        <strong><xsl:value-of select="." /></strong>
    </xsl:template>

 

注意上面的value-of的select是使用的 "." ,而沒有使用"/bank/p/name",因為"/bank/p/name"返回的是所有的name元素," . "表示模版當前應用的那個元素!

可以定義多個模版,如下:

    <xsl:template match="/bank/p/name">
        <strong><xsl:value-of select="." />---</strong>
    </xsl:template>
    <xsl:template match="/bank/p/age">
        <em><xsl:value-of select="." />---</em>
    </xsl:template>
    <xsl:template match="/bank/p/money">
        <u><xsl:value-of select="." /></u><hr />
    </xsl:template>

 

當多個模版的match表達選取節點重疊時,後出現的模版的格式會覆蓋先出現的,可以使用template元素的priority屬性對模版的優先組進行編號,其值是一個數字,越大優先順序越高!

這樣,便給name,age,money這些元素都進行了格式化輸出,但現在輸出的HTML程式碼順序仍然是按照在XML原始檔中出現的順序出現的.當需要對整個XML文件進行格式化輸出的時候,可以將match屬性設為"/"

    <xsl:template match="/" />

 

使用上面的模版,將會使XML文件在瀏覽器中沒有任何輸出.可以在應用於根節點的模版中加上HTML標籤,以輸出完整的HTML文件!

    <xsl:template match="/">
        <html>
        <head>
            <title>XSLT</title>
        </head>
        <body>
            一個HTML頁面
        </body>
        </html>
    </xsl:template>

 

這樣,即使定義了其它模版,它們的輸出也不會出現在瀏覽器中,因為上面的模版覆蓋了其它應用於子節點的模版的輸出,要在其中包含其它模版的內容,可以使用XSLT的apply-templates元素來應用模版,該元素有兩個屬性,select屬性值是一個XPath表示式,XPath表示式選取的節點及其子節點將被應用模版. 如果沒有為這些節點定義模版,則直接輸出節點的值.如果apply-templates元素不指定select屬性,則將給當前節點(template元素的match屬性所匹配的節點)的所有後代節點應用模版,如果沒有定義模版,則直接輸出所有節點的值.

下面的程式碼將直接輸出所有節點的值

XSLT中有一個規定:如果一個節點沒有任何可用的template,則將這個節點中所有文字節點的值返回!

    <xsl:template match="/">
            <xsl:apply-templates />
    </xsl:template>

 

可以指定select屬性,指明哪些節點將應用模版並輸出在這個地方,這樣就可以不以XML原始檔中的順序輸出資料了!

    <xsl:template match="/">
        <xsl:apply-templates select="/bank/p/money" />
            <hr />
        <xsl:apply-templates select="/bank/p/name" />
    </xsl:template>

 

還可以使用call-template呼叫指定的模版,call-template元素的name屬性指定要呼叫模版的name

attribute 給元素新增屬性

使用attribute元素,可以在轉換時給元素動態新增屬性!其語法很簡單,下面是一個給img元素新增值為"test.jpg"的src屬性的程式碼:

    <img>
        <xsl:attribute name="source">test.jpg</xsl:attribute>
    </img>

 

for-each 節點遍歷

XSLT中的for-each 元素允許您在 XSLT 中進行迴圈。該元素的select屬性與其它元素的select屬性一樣,其值是一個XPath表示式,被XPath表示式選取的元素將被遍歷!

    <xsl:template match="/">
        <xsl:for-each select="/bank/p/name">
            <em><xsl:value-of select="." /></em><br />
        </xsl:for-each>
    </xsl:template>

 

上面的程式碼將遍歷所有根元素bank的子元素p的name子元素並加以格式化後輸出它的值. 注意,value-of元素的select的值"."表示選取當前節點,在for-each的內部,當前節點為for-each當前遍歷到的節點!

sort 排序

sort 元素用於對結果進行排序。sort元素需要放在for-each元素內部.sort元素的select屬性值為選取排序依據節點的XPath表示式,data-type屬性有兩個取值(text|number),指明是按字母順序排序還是按數字大小排序! 另外,它還有個order屬性,可以指定是按正順還是倒序排序,取值為(ascending|descending),預設是ascending(正序)!

    <xsl:for-each select="/bank/p">
        <xsl:sort select="./money" data-type="number" />
        <xsl:value-of select="./money" /><br />
    </xsl:for-each>

 

if 條件測試

在XSLT中還可以使用if元素進行條件判斷,該元素的test屬性值為一個條件測試XPath表示式,當值計算結果是真的時候才處理if元素中的內容!

    <xsl:for-each select="/bank/p">
        <xsl:sort select="./money" data-type="number"  order="descending" />
        <xsl:if test="position() &lt; 4 and age &gt;=18">
            <xsl:value-of select="./money" /><br />
        </xsl:if>
    </xsl:for-each>

 

上面的程式碼用以輸出money排前三名的成年人. 注意,在if元素的test屬性中,XPath表達中的一些特殊字元(如大於和小於)必須寫成實體引用!

choose when...otherwise...... 多重條件測試

出於習慣,見到if語句可能會想到if...else語句,但XSLT中並沒有if..else語句,取而代之的是即有if...else功能,又有switch..case功能的choose元素,choose元素有兩個子元素when與otherwise,相當於 else if 與else ,或者,when相當於case語句,otherwise相當於default.when元素的test屬性值同樣是一個XPath表示式,當這個表示式返回真的時候,when的子元素才會顯示!otherwise沒有test屬性,當所有的when元素的test都失敗後,處理otherwise子元素!

    <xsl:choose>
        <xsl:when test="name='PHPer'">PHPer就是PHP程式設計師的意思!</xsl:when>
        <xsl:when test="name='CJ'">好好Coding,天天向上!</xsl:when>
        <xsl:when test="name='DBD'">不懂!</xsl:when>
        <xsl:otherwise>其它人</xsl:otherwise>
    </xsl:choose>

 

瀏覽器中的 XSLT

只要有XML與XSLT解釋引擎,就可以在任何地方使用任何語言利用XSLT將XML轉換成HTML或其它文件,並且使用不同的語言並不會影響轉換結果.也就是說,這種轉換是與語言無關的,既可以在伺服器端進行轉換後,返回HTML頁面,也可以客戶端進行轉換,它們的效果都是一樣的.而且在客戶端對XML檔案進行轉換,可以減輕伺服器的負擔.

在一個引入了XSLT檔案的XML檔案,瀏覽器會自動對其進行轉換.但是,XML一般並不是在瀏覽器中顯示,而是用來讀取資料.當使用其它語言來手動轉換時,需要將xml-stylesheet這樣的PI去掉,這樣,XML 檔案可使用多個不同的 XSL 樣式表來進行轉換,增加了靈活性。

IE 中的XSLT

與IE支援XML DOM 一樣,IE中XSLT相關API顯得十分簡單,同時IE對XSLT的支援也很有限!下面是在IE 中將一個XMLDOM使用XSLT轉換成HTML的示例:

    //載入XML資料檔案
    var xml = new ActiveXObject("Microsoft.XMLDOM");
    xml.async = false;
    xml.load("test.xml");
    //載入XSLT檔案,XSLT也是作為XML檔案載入的
    var xsl = new ActiveXObject("Microsoft.XMLDOM");
    xsl.async = false;
    xsl.load("test.xsl");
    //直接在要轉換的DOM上呼叫transformNode方法,傳入XSLT DOM,返回字串
    document.write(xml.transformNode(xsl));

 

Mozilla 中的XSLT

與Mozilla對XML DOM的支援一樣,它對XSLT的支援更標準但更復雜!Mozilla使用一個XSLTProcessor物件來處理與XSLT有關的轉換.

    //載入XML資料
    var xml = document.implementation.createDocument("","",null);
    xml.async =false;
    xml.load("test.xml");
    //載入XSLT
    var xsl = document.implementation.createDocument("","",null);
    xsl.async =false;
    xsl.load("test.xsl");
    //建立XSLTProcessor
    var xslPro = new XSLTProcessor();
    xslPro.importStylesheet(xsl);//匯入XSLT
    //使用transformToDocument將XML按XSLT進行轉換,返回新文件的DOM
    var result = xslPro.transformToDocument(xml);
    //要將返回的DOM轉換成字串,還要使用XMLSerializer物件
    var serializer =new XMLSerializer();
    var html = serializer.serializeToString(result);
    document.write(html);

 

相關文章