<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    XSL入門(翻譯)

    1. XSL處理模型

    XSL是一個模板語言,而不是一個程序語言。這意味著stylesheet制定了一個輸出樣本,而不是使用程序按步驟生成。一個stylesheet包含了一個混合的輸出樣本,并且為每個樣本佩戴了輸出指令。每一個曉得輸出樣本加上處理指令就構成了一個模板。

    通常情況,你要為文檔內(nèi)的每個元素書寫一個模板。這樣能夠讓你每次只專注于一個元素,并持有一個stylesheet模塊。XSL的強大之處在于它能夠遞歸的處理模板,也就是說,每個模板只處理它對應的一個元素,然后調(diào)用其它模板來處理它的子元素,以此類推。一個XML文檔總是用一個根元素作為頂層元素,并包含可以嵌套的子元素,XSL模板總是從頂層開始掃描,并照層級來處理元素。

    現(xiàn)在用Docbook的<para>元素為例子,要把它轉(zhuǎn)換成HTML,你希望使用HTML標記<p>來包圍要輸出的內(nèi)容。但是DocBook的<para>元素可以包含任何in-line類型的元素來標記內(nèi)容;不用擔心,你可以讓其它對應的模板來處理這些元素,因此你的<para>XSL模板會是下面這樣的簡單:
    <xsl:template match="para">   <p>     <xsl:apply-templates/>   </p> </xsl:template>

    元素<xsl:template>表示開始一個新的模板,屬性match聲明什么元素要被應用模板,在這個例子中將匹配任何的<para>元素。模板指出要輸出一個<p>并執(zhí)行<xsl:apply-template>指令。這將告訴XSL處理器在stylesheet內(nèi)尋找所有的模板并將其應用到段落中的元素。如果stylesheet每個模板都含有一個<xsl:apply-template>指令,那么將會遞歸執(zhí)行下去。當執(zhí)行到stylesheet的末尾時,模板將輸出一個結束的</p>標簽。

    1.1. 重要的上下文環(huán)境

    既然不需要用線性的步驟來書寫你的文檔,那么一個用來描述在什么地方應用這些模板的“上下文環(huán)境”是尤為重要的。大多數(shù)模板都提供了一個match屬性來描述上下文環(huán)境,這是一個純粹的表達式語言:XPath,用來標識你文檔中的哪個部分將被應用這個模板。簡單的上下文環(huán)境通常只聲明一個元素名,就像上面的例子。但是你也可以指定元素的子元素,子元素也可以指定屬性值,指定的元素成一個隊列的形式,以此類推。下面的模板例子描述如何匹配DocBook的<formalpara>元素
    <xsl:template match="formalpara">   <p>     <xsl:apply-templates/>   </p> </xsl:template>  <xsl:template match="formalpara/title">   <b><xsl:apply-templates/></b>   <xsl:text> </xsl:text> </xsl:template>  <xsl:template match="formalpara/para">   <xsl:apply-templates/> </xsl:template>

    上面定義了三個模板,第一個應用于<formalpara>元素本身,另外兩個應用其子元素。在第二個模板中的match屬性是一個XPath表達式,用來表示這里的<title>元素是一個直接隸屬與<formalpara>元素的子元素。這就區(qū)分與在DocBook中的其它<title>元素。XPath表達式是控制模板如何應用的關鍵。

    通常情況,XSL處理器的內(nèi)部規(guī)則是在面對高層模板和底層模板時,優(yōu)先應用底層模板,這里的層次是元素的層級,文檔頂層是高層元素,以此類推。這能夠讓你更細致的控制模板應用,但是在你沒有為復雜的符合元素提供細致的上下文環(huán)境時,XSL處理器也對其提供了備選方案。這個特性在上面的例子中得以體現(xiàn),對于formalpara/para,例子中提供的第三個模板,<para>元素作為<formalpara>元素的子元素,處理器將使用單獨的方式來處理它,它將不會再輸出已經(jīng)被父元素輸出的<p>HTML標簽。如果formalpara/para模板沒有包含在上面的例子中,那么處理器將使用備選的模板match="para",這個模板在上一個例子中定義。這樣處理器將輸出第二層<p>HTML標簽。

    你也可以使用XSL中的modes來控制模板上下文環(huán)境,這種方式已經(jīng)被廣泛應用與DocBook stylesheet中。Modes能夠讓你使用不同的方式來處理相同的輸入。在<xsl:template>模板定義中使用mode屬性將會為模板指定一個mode命名。這種情況下,當有兩個模板指定了相同的mode屬性值,處理器將把math的屬性值和mode的屬性值通過表達式and連接來作為一個過濾條件,也就是說,當mode屬性值相同時則繼續(xù)使用match屬性值匹配來區(qū)分使用哪個模板。這就讓你對一個元素定義了兩個不同的模板來針對不同的上下文環(huán)境。例如,下面對DocBook的<listitem>元素定義了兩個不同的模板:
    <xsl:template match="listitem">   <li><xsl:apply-templates/></li> </xsl:template>  <xsl:template match="listitem" mode="xref">   <xsl:number format="1"/>   </xsl:template>

    第一個模板應用于普通的列表輸出情況,模板輸出<li>HTML標簽來。第二個模板定義為<xsl:apply-templates select="$target" mode="xref"/>,這種情況下用來專門處理<xref>元素。在這個例子中,mode屬性的值決定應用第二個模板,它將初始帶有序號的列表。因為在輸出<xref>元素時經(jīng)常會有這樣的需求。

    請記住,mode的設置不會自動的貫穿處理子模板<xsl:apply-templates/>。當子模板含有mode屬性時,你可以有兩個選擇來處理:
    • 要想繼續(xù)使用mode模式,也就是使用<xsl:apply-templates mode="mode"/>模板來處理子元素,處理器將查找具有相同mode屬性值的模板來應用子元素。注意,這樣的話你就沒有備選方案,如果模板沒有指定mode屬性值,子元素將不會有模板匹配,也就不會被模板處理。如果你想使用沒有mode屬性的模板作為備選,那么在stylesheet中加入下面的模板:
      <xsl:template  match="*"  mode="mode">   <xsl:apply-templates select="." /> </xsl:template>

      這樣的話,對于任何子元素,如果模板沒有配備mode屬性值,那么模板也將會被應用
    • 使用通常的無mode模板,對子元素使用<xsl:apply-templates/>,你可以定義無mode模板

    1.2. 編程特性

    盡管XSL是模板驅(qū)動的,但是它同樣具有很多傳統(tǒng)編程語言的特性。下面一些例子來自與DockBook stylesheet
    Assign a value to a variable: <xsl:variable name="refelem" select="name($target)"/>  If statement: <xsl:if test="$show.comments">     <i><xsl:call-template name="inline.charseq"/></i> </xsl:if>  Case statement: <xsl:choose>     <xsl:when test="@columns">         <xsl:value-of select="@columns"/>     </xsl:when>     <xsl:otherwise>1</xsl:otherwise> </xsl:choose>  Call a template by name like a subroutine, passing parameter values and accepting a return value: <xsl:call-template name="xref.xreflabel">    <xsl:with-param name="target" select="$target"/> </xsl:call-template> 

    然而你不能像在其它編程語言那樣來使用上面這些結構,因為變量在特別的情況下會具有完全不同的行為。

    1.2.1. 使用變量和參數(shù)

    XSL提供兩種元素來讓你指派值到變量上:<xsl:variable><xsl:param>。它們享用共同的命名空間和語法,都使用$name來引用變量。這兩個元素最主要的不同是param's的默認值能夠被模板調(diào)用的<xsl:with-param>所取代,就如上面最后一個例子所示。

    下面兩個例子同樣來自DocBook:
    <xsl:param name="cols">1</xsl:param> <xsl:variable name="segnum" select="position()"/>

    在上面兩個元素中,paramvariable的名字都是通過name屬性來指定的,可以看到param的名字是colsvariable的名字是segnum。它們的值可以通過兩種方式來提供,參數(shù)的例子是通過元素的內(nèi)容值“1”來賦值的,而變量的例子是通過select屬性值來賦值的,這個屬性值是一個表達式的結果,而元素本身并沒有內(nèi)容值。

    對于新接觸XSL的用戶來說變量的特性有點古怪,當你給一個變量賦值后,你就不能在它的應用周期內(nèi)改變它的值,如果這樣做會報錯。所以你不能像在使用其它編程語言那樣對變量進行動態(tài)存儲,變量在它的應用周期內(nèi)持有的是固定值,并在應用周期結束時銷毀。這個特性是在設計XSL時就決定了,因為XSL是模板驅(qū)動而非流程驅(qū)動的。這意味著它沒有固定的執(zhí)行順序,所以你無法依賴一個能夠改變值的變量。要想正確的使用變量,你必須理解變量的周期是如何定義的。

    如果一個變量定義在所有模板的外部,那么它就被認為是一個全局變量,它對所有模板都生效。全局變量的值是固定不變的,也不能被任何模板所重新賦值。但是你可以在模板內(nèi)創(chuàng)建一個與全局變量同名的本地變量,然后賦予其它的值。本地變量只能在其自己的應用周期內(nèi)起作用。

    定義在模板里的本地變量只會在它被允許的周期內(nèi)生效,也就是對在它之后的同胞和后裔有效。要想理解這個周期,你必須明白XSL指令其實就是純粹的XML元素,并內(nèi)嵌在XML家族層級結構中。它們通常是指父級、子級、同級、祖先級和后裔級。在XML家族層級中,給一個變量賦值就像發(fā)布一個公告給你希望聽到家族成員一樣。你只能把公告發(fā)布給比你年齡低的同級(包括你自己)和它們的后裔級,也就是說定義在你前面的年長的同級將不會聽到公告,更不用說你的父級和祖先了。如果你發(fā)布不同的公告內(nèi)容但是用相同的公告名給相同的被通知成員,那將出現(xiàn)錯誤,(言外之義,你重新給變量賦值了)。請記住這里的家族并不是你的文檔元素,而只是在你stylesheet中的XSL指令。手工編寫stylesheet將對你跟蹤周期很有幫助,XSL元素縮進和嵌套將幫助你理解周期。下面的代碼片段來自DocBook stylesheet中的pi.xsl文件,舉例說明兩個變量周期的不同。
     1 <xsl:template name="dbhtml-attribute">  2 ...  3    <xsl:choose>  4       <xsl:when test="$count>count($pis)">  5          <!-- not found -->  6       </xsl:when>  7       <xsl:otherwise>  8          <xsl:variable name="pi">  9             <xsl:value-of select="$pis[$count]"/> 10          </xsl:variable> 11          <xsl:choose> 12             <xsl:when test="contains($pi,concat($attribute, '='))"> 13                <xsl:variable name="rest" select="substring-after($pi,concat($attribute,'='))"/> 14                <xsl:variable name="quote" select="substring($rest,1,1)"/> 15                <xsl:value-of select="substring-before(substring($rest,2),$quote)"/> 16             </xsl:when> 17             <xsl:otherwise> 18             ... 19             </xsl:otherwise> 20          </xsl:choose> 21       </xsl:otherwise> 22    </xsl:choose> 23 </xsl:template>

    變量pi的周期開始于第8行,也就是模板定義它的位置,結束于第20行它最后一個同級兄弟結束的地方[1]。變量rest的周期開始于13行,結束與15行。幸運的是,15行的輸出表達式趕在周期結束前使用了變量值。

    讓我們來看看當在變量的周期內(nèi)使用<xsl:apply-templates/>會如何?被應用的模板內(nèi)會得到變量值嗎?答案是否定的。因為被應用的模板生效周期并沒有真正的在變量周期內(nèi),它在stylesheet的其它地方退出,并不是在變量的低齡同級和后裔內(nèi)退出。

    要想傳值給一個模板,你可以使用<xsl:with-param/>傳遞一個參數(shù)。這種參數(shù)傳遞通常被用在使用<xsl:call-templates/>調(diào)用指定模板,盡管你也可以使用<xsl:apply-templates/>調(diào)用模板,但是通常被調(diào)用的模板希望傳入一個與<xsl:param/>定義同名的參數(shù)。這樣就可以在模板內(nèi)使用這個參數(shù)值。任何傳入的參數(shù)名如果在模板內(nèi)沒有被定義將被忽略處理。

    下面參數(shù)傳遞的例子來自docbook.xsl
    <xsl:call-template name="head.content">    <xsl:with-param name="node" select="$doc"/>    </xsl:call-template>

    上面一個命名為head.content的模板被調(diào)用,在調(diào)用周期內(nèi)傳遞了一個名為node的參數(shù),參數(shù)值是變量$doc。上面被調(diào)用的模板看上去會是下面的樣子:
    <xsl:template name="head.content">    <xsl:param name="node" select="."/>    ...

    模板期望一個參數(shù)是因為模板定義中聲明了一個<xsl:param/>,并且名字和傳入?yún)?shù)名相同。模板內(nèi)的<xsl:param/>提供了一個默認值,如果傳入的參數(shù)名沒有與其匹配,那么將在模板內(nèi)使用默認值。

    1.3. 生成HTML

    從你的DocBook文件生成HTML需要使用HTML版本的stylesheet,這些由stylesheet的HTML驅(qū)動文件docbook/html/docbook.xsl來完成。這是一個主stylesheet文件,它使用<xsl:include/>導入其它組件文件組裝一個完整的stylesheet用來生成HTML

    DocBook stylesheet生成HTML的方式是通過應用模板來輸出一些文本內(nèi)容和HTML元素的混合體。從docbook.xsl的頂層開始:
    <xsl:template match="/">   <xsl:variable name="doc" select="*[1]"/>   <html>   <head>     <xsl:call-template name="head.content">       <xsl:with-param name="node" select="$doc"/>     </xsl:call-template>   </head>   <body>     <xsl:apply-templates/>   </body>   </html>   </xsl:template>

    模板匹配到你輸入文檔的根元素,然后就開始遞歸應用模板。首先定義了一個變量doc,然后輸出兩個HTML元素<html><head>。接著調(diào)用名為head.content模板來處理HTML的<head>,關閉<head>后就開始<body>。這里使用<xsl:apply-templates/>來遞歸處理輸入文檔中的內(nèi)容,最終關閉像HTML文件的輸出。

    簡單的HTML元素可以用不帶任何屬性的元素生成,如<html>,但是如果HTML元素輸出依賴上下文環(huán)境,你就需要一個強大的機制來選取輸出元素并且還會生成它們的屬性和屬性值。下面的代碼片段來自于sections.xsl,其展示了用<xsl:element><xsl:attibute>來生成HTML的頭標簽
     1 <xsl:element name="h{$level}">  2   <xsl:attribute name="class">title</xsl:attribute>  3   <xsl:if test="$level<3">  4     <xsl:attribute name="style">clear: all</xsl:attribute>  5   </xsl:if>  6   <a>  7     <xsl:attribute name="name">  8       <xsl:call-template name="object.id"/>  9     </xsl:attribute> 10     <b><xsl:copy-of select="$title"/></b> 11   </a> 12 </xsl:element>

    整個例子生成了一個單獨的HTML頭元素。第1行定義了一個HTML元素,例子中元素的名字是一個帶有變量$level的表達式,變量是通過參數(shù)出入模板的。這樣的話模板就會生成<hi><h2>、等等。具體生成哪個依賴于上下文環(huán)境。第2行為頭元素添加了一個屬性class="title"。第3-5行添加了屬性style="clear all",但是只適用于頭元素的層級數(shù)小于3的情況。第6行打開一個錨元素<a>。看上去沒帶有任何屬性,其實是在第7-9行為<a>元素添加了name屬性。這個例子描述XSL管理的輸出元素是一個活的元素,而不只是一個文本串。第10行輸出頭元素的標題文本,同樣是通過傳遞參數(shù)的形式獲得,然后關閉HTML粗體標簽。第11行使用</a>關閉錨標簽,第12行是頭元素的關閉標簽,這就結束了頭元素的定義。

    當你隨著模板的遞歸來處理元素時,可能會疑惑在你文檔里的內(nèi)容文本是如何被模板輸出的,在docbook.xsl文件中你會找到如下的模板,它專門用來內(nèi)容文本。
    <xsl:template match="text()">   <xsl:value-of select="."/> </xsl:template>

    這個模板的主體由文本節(jié)點的值組成,它只是文本。通常,如果你的stylesheet中沒有提供匹配的模板,XSL處理器都有一些內(nèi)建的模板來獲取內(nèi)容文本。上面的模板就是提供這樣的功能,只不過它明確定義在stylesheet文件中。

    1.4. 生成格式化對象(FO)

    使用fo版本的stylesheet可以把你的DocBook XML生成格式化對象。這里需要在你的stylesheet中使用docbook/fo/docbook.xsl。在你的主stylesheet文件中使用<xsl:include>引入所有的組件組裝成完整的stylesheet來生成格式化對象。生成格式化對象只完成了輸出過程的一半,你還需要使用XSL-FO處理器,比如FOP。

    DocBook的fo stylesheet和HTML stylesheet的工作方式類似,就是用<fo:something>形式的標簽代替相應的HTML標簽。例如,輸出in-line類型并且使用monospace字體,fo的形式會是如下的樣子:
    <fo:inline-sequence  font-family="monospace">/usr/man</fo:inline-sequence>

    輸出一個DocBook <filename>元素,在docbook/fo/inline.xsl中的模板定義看起來像如下的樣子:
    <xsl:template match="filename">   <xsl:call-template name="inline.monoseq"/> </xsl:template>  <xsl:template name="inline.monoseq">   <xsl:param name="content">     <xsl:apply-templates/>   </xsl:param>   <fo:inline-sequence font-family="monospace">     <xsl:copy-of select="$content"/>   </fo:inline-sequence> </xsl:template>

    在XSL標準中指定了很多XSL-FO標簽和屬性的規(guī)范,要描述在DocBook中如何遵循這些規(guī)范顯然已經(jīng)超出本書的范圍。慶幸的是,這些只是中間格式,你不許要馬上去處理,除非你正在自己編寫stylesheets

    posted on 2011-03-09 08:58 kuuyee 閱讀(1576) 評論(1)  編輯  收藏 所屬分類: 系統(tǒng)管理JEE

    評論

    # re: XSL入門(翻譯)[未登錄] 2011-03-09 09:18 paul

    用他搞過代碼生成工具  回復  更多評論   

    導航

    <2011年3月>
    272812345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    統(tǒng)計

    隨筆分類(139)

    Linux內(nèi)核

    搜索

    •  

    積分與排名

    • 積分 - 319375
    • 排名 - 177

    最新評論

    閱讀排行榜

    主站蜘蛛池模板: 青柠影视在线观看免费高清| 亚洲午夜福利精品久久 | 女人18毛片免费观看| 日韩高清免费在线观看| 免费人成在线观看网站品爱网| 西西人体大胆免费视频| 亚洲欧美成aⅴ人在线观看| 亚洲精品在线播放| 亚洲AV无码久久精品蜜桃| 亚洲精品综合久久| 国产成人aaa在线视频免费观看| 免费看污成人午夜网站| 1000部国产成人免费视频| 午夜视频在线免费观看| a级毛片免费观看视频| 黄色短视频免费看| 一级毛片免费视频网站| 免费国产污网站在线观看不要卡| 亚洲国产精品无码久久98| 亚洲熟妇无码AV不卡在线播放| 亚洲国产综合自在线另类| 亚洲综合激情六月婷婷在线观看| 亚洲高清在线观看| 久久久久亚洲AV成人无码 | 中文字幕免费人成乱码中国| 特级毛片免费观看视频| 国产在亚洲线视频观看| 亚洲AV成人一区二区三区观看| 亚洲中文字幕久久精品无码A| 精品日韩99亚洲的在线发布| 亚洲无限乱码一二三四区| 亚洲免费网站在线观看| 亚洲av日韩av无码av| 亚洲sss综合天堂久久久| 91丁香亚洲综合社区| 国产亚洲精品bv在线观看| 亚洲综合精品伊人久久| 亚洲AV无码之国产精品| 美女隐私免费视频看| 九九全国免费视频| 三上悠亚电影全集免费|