2009-06-04 54 views
3

我有一個現有的XSLT樣式表,它採用XML並生成格式良好的XHTML。我想使這個樣式表的XSL-FO版本通過Apache FOP生成PDF。我想知道的是:使用XSLT生成XSLT有哪些有用的結構?

是否有方便使用XSLT模式我需要學會做這樣的事情:

  • 複製一些節點不變
  • 複製大多數的節點,但加入附加屬性

我知道我可以用創造新的節點

<xsl:element> 

,但是我還需要其他有用的東西。請注意,儘管我沒有做過很多從一種XSLT格式到另一種XSLT格式的複製,但我已經通過XSLT完成了XML-> XHTML,所以我熟悉了該語言的大部分核心。

回答

8

你正在尋找的模式是「修改的身份變換」。這種方法的基礎是身份轉換規則,這是下面樣式表中的第一個模板規則。之後的每條規則都表示複製行爲的例外。

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <!-- By default, copy all nodes unchanged --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <!-- But strip out <foo> elements (including their content) --> 
    <xsl:template match="foo"/> 

    <!-- For <bar> elements, strip out start & end tags, but leave content --> 
    <xsl:template match="bar"> 
    <xsl:apply-templates/> 
    </xsl:template> 

    <!-- For <bat> elements, insert an attribute and append a child --> 
    <xsl:template match="bat"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:attribute name="id">123</xsl:attribute> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

對我而言,最不滿意的是上面的模板規則中的邏輯重複。這只是添加一個屬性的很多代碼。想象一下,如果我們需要一堆這些。這裏是另一種方法,使我們能夠在我們要覆蓋哪些更多的手術精確:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <!-- By default, copy all nodes unchanged --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates mode="add-atts" select="."/> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

      <!-- By default, don't add any attributes --> 
      <xsl:template mode="add-atts" match="*"/> 

    <!-- For <bat> elements, insert an "id" attribute --> 
    <xsl:template mode="add-atts" match="bat"> 
    <xsl:attribute name="id">123</xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 

最後,這可以更進一步使用各種編輯的不同的方式進行,你可能想使:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <!-- For <bat> elements, insert an "id" attribute --> 
    <xsl:template mode="add-atts" match="bat"> 
    <xsl:attribute name="id">123</xsl:attribute> 
    </xsl:template> 

    <!-- Append <new-element/> to <bat> --> 
    <xsl:template mode="append" match="bat"> 
    <new-element/> 
    </xsl:template> 

    <!-- Insert an element in <foo> content --> 
    <xsl:template mode="insert" match="foo"> 
    <inserted/> 
    </xsl:template> 

    <!-- Add content before the <bar/> and <bat/> elements --> 
    <xsl:template mode="before" match="bar | bat"> 
    <before-bat-and-bar/> 
    </xsl:template> 

    <!-- Add content only after <bat/> --> 
    <xsl:template mode="after" match="bat"> 
    <after-bat/> 
    </xsl:template> 

    <!-- Here's the boilerplate code --> 
    <!-- By default, copy all nodes unchanged --> 
    <xsl:template match="@* | node()"> 
    <xsl:apply-templates mode="before" select="."/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates mode="add-atts" select="."/> 
     <xsl:apply-templates mode="insert" select="."/> 
     <xsl:apply-templates/> 
     <xsl:apply-templates mode="append" select="."/> 
    </xsl:copy> 
    <xsl:apply-templates mode="after" select="."/> 
    </xsl:template> 

      <!-- By default, don't add anything --> 
      <xsl:template mode="add-atts" match="*"/> 
      <xsl:template mode="insert" match="*"/> 
      <xsl:template mode="append" match="*"/> 
      <xsl:template mode="before" match="@* | node()"/> 
      <xsl:template mode="after" match="@* | node()"/> 

</xsl:stylesheet> 

在XSLT 2.0,一些樣板可以稍作簡化,由於多模模板規則:

  <!-- By default, don't add anything --> 
      <xsl:template mode="add-atts 
           insert 
           append 
           before 
           after" match="@* | node()"/> 

我有時會使用所有這些自定義模式在相同的樣式表中,但更多的時候我會懶惰地添加它們 - 根據需要。

3

變換XSLT的最大障礙是輸出名稱空間前綴與變換中的實際XSL指令的前綴相同。如果在XSL指令和輸出中都使用「xsl:」,那麼XSLT引擎就不會知道它應該執行的XSL指令與它應該輸出的XSL指令之間的區別,所以XSLT不會被解析。也就是說,除非你使用一個命名空間別名:

<xsl:namespace-alias stylesheet-prefix="x" result-prefix="xsl"/> 

該指令,這是擺的<xsl:stylesheet />裏面,讓你寫你的結果標記在您的轉換使用替代品命名空間前綴。稍後,在創建輸出文檔時,您實際需要的前綴將插入到別名的位置。所以,舉例來說,這裏是你的輸出文檔中生成模板的模板:

<xsl:template match="xsl:template[@match='title']> 
    <x:template match="title> 
     <x:apply-templates /> 
    </x:template> 
</xsl:template> 

這裏有一個很好的文章:http://www.xml.com/pub/a/2001/04/04/trxml/

+0

那麼,xslt有一個「另一個xslt命名空間」,你可以使用它! – alamar 2009-06-05 19:06:02

+1

http://www.w3.org/1999/XSL/Transform是一個普通的命名空間,而http://www.w3.org/1999/XSL/TransformAlias是另一個:) – alamar 2009-06-05 19:10:35

0

在過去,我開發了XSL-FO樣式表,然後使用Render-X FO2HTML stylesheet將XSL-FO轉換爲HTML。它把<block>元素融入<div><inline><span>

我以前沒有使用過他們,但你可能會考慮嘗試HTML2FO stylesheets。或者至少看他們借用一些想法。

由於HTML缺乏FO提供的某些分頁結構,因此可能無法爲您提供XSL-FO輸出所需的全部內容,但可以處理大部分從HTML到XSL-FO元素的轉換邏輯/文檔正文中的屬性。