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

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

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

    MDA之路

    MDA,UML,XML,Eclipse及Java相關的Blog
    posts - 53, comments - 494, trackbacks - 0, articles - 2
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    一個XSLT的變量、參數和模板調用的問題

    Posted on 2006-03-08 22:52 wxb_nudt 閱讀(7858) 評論(4)  編輯  收藏 所屬分類: 技術雜談

    1.     問題

    昨天遇到了這樣一個xml文檔,如下:bookObject.xml

    <?xml version="1.0" encoding="ASCII"?>

    <?xml-stylesheet type="text/xsl" href="Book2PubXSLT.xsl"?>

    <xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI">

    <Book title="WxbBook">

               <chapters nbPages="12" title="chapter1" author="author1"/>

               <chapters nbPages="15" title="chapter2" author="author2"/>

               <chapters nbPages="20" title="chapter3" author="author3"/>

    </Book>

    <Book title="nextBook">

               <chapters nbPages="10" title="chapter1" author="aaa"/>

               <chapters nbPages="20" title="chapter2" author="bbb"/>

               <chapters nbPages="30" title="chapter3" author="ccc"/>

    </Book>

    </xmi:XMI>

    希望能夠使用XSLT轉換為這樣的一個xml文檔(目的是為了做一個很簡單的模型轉換實例,當然這點和本文主題幾乎無關):publicationObject.xml

    <?xml version="1.0" encoding="ASCII"?>

    <xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="Publication">

    <Publication title="nextBook" nbPages="60" authors="ccc and aaa and bbb"/>

    <Publication title="WxbBook" nbPages="47" authors="author3 and author1 and author2"/>

    </xmi:XMI>

    分析這兩個文檔可以看出,希望的轉換規則如下:

    Book節點有一個屬性title,它等于Publication的節點屬性title。

    Book節點包含chapters子節點,每個子節點都有三個屬性。其中一個Book節點的所有chapters子節點的nbPages屬性相加等于PublicationnbPages屬性;

    一個Book節點的所有chapters子節點的author相連,并在中間插入and則等于Publicationauthors屬性。

    由于之前我并沒有接觸過XSLT的變量、參數和xsl:call-template等概念,所以還是頗費了一點時間來解決此問題。

    2.     問題的解決

    值得注意的有幾點:

    1.              XSLT中的變量一次賦值后是不能改變的,所以這里的變量幾乎等于其它語言中的常量。

    2.              template有兩種,常見的是通過<xsl:template match="/">這樣的方式定義的,使用match屬性。調用的時候是使用<xsl:apply-templates select=""/>。另一種template類似與其它語言中的函數調用,使用<xsl:template name=”t_name”>來定義,調用的時候使用<xsl:call-template name=" t_name "/>來調用。

    3.              在第二種template的定義中可以加入參數,類似于其它編程語言中的參數列表。在調用時也可以傳入具體的值做為實參。

    4.              由于XSLT不包含for、while等循環語句。當簡單的for-each不能滿足要求時。則需要使用遞歸template調用來完成其它語言中的循環。從functional programming的理論中我們知道這二者是等價的。

    下面是進行轉換的XSL文檔:Book2PubXSLT.xsl

    <?xml version="1.0" encoding="ASCII"?>

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:xmi="http://www.omg.org/XMI">

    <xsl:template name="left">

    <xsl:text disable-output-escaping="yes">&lt;</xsl:text>

    </xsl:template>

    <xsl:template name="right">

    <xsl:text disable-output-escaping="yes">&gt;</xsl:text>

    </xsl:template>

     

    <xsl:template match="/">

    <xsl:call-template name="left"/>xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="Publication"<xsl:call-template name="right"/>

               <xsl:apply-templates select="xmi:XMI"/>

               <xsl:call-template name="left"/>/xmi:XMI<xsl:call-template name="right"/>

    </xsl:template>

    <xsl:template match="xmi:XMI">

               <xsl:for-each select="Book">

               <xsl:call-template name="left"/>Publication title="<xsl:value-of select="@title"/>"

                               nbPages ="<xsl:value-of select="sum(chapters/@nbPages)"/>"

                  authors ="

                        <xsl:call-template name="concatAuthor">

                                 <xsl:with-param name="str" select="chapters/@author"/>

                                 <xsl:with-param name="index" select="1"/>

                                 <xsl:with-param name="nodenum" select="last()+1"/>

                        </xsl:call-template>"/<xsl:call-template name="right"/>

               </xsl:for-each>

    </xsl:template>

    <xsl:template name="concatAuthor">

               <xsl:param name="str"/>

               <xsl:param name="index"/>

               <xsl:param name="nodenum"/>

               <xsl:choose>

                        <xsl:when test="$index != $nodenum">

                                 <xsl:call-template name="concatAuthor">

                                           <xsl:with-param name="str" select="concat($str,' and ',chapters[$index+1]/@author)"/>

                                           <xsl:with-param name="index" select="$index + 1"/>

                                           <xsl:with-param name="nodenum" select="$nodenum"/>

                                 </xsl:call-template>

                        </xsl:when>

                        <xsl:otherwise>

                                 <xsl:value-of select="$str"/>

                        </xsl:otherwise>

               </xsl:choose>

    </xsl:template>

    </xsl:stylesheet>

    從上面可以看出,解決問題最主要的一點就是使用了一個遞歸模板concatAuthor,它帶有三個參數str,index nodenum,分別表示連接的字符串、迭代子和chapters的節點數。通過這種方法,熟悉遞歸的人可以很快的寫出幾乎和javascript等價的種種數據操作。當然,由于變量不能賦值、參數只能以遞歸的方式來改動,還是很不方便的。

    其優點也是明顯的,不依賴其它腳本語言完成了數據操作。可以在所有xsl引擎上面運行。

    3.     小結

    深入講解XSLT的中文文獻不多,大多數是入門級的。當我半猜半試的解決了這個問題后。發現了在O’Reilly有一本《XSLT》的書,其中列出了這樣的內容。
           哦,今天是女孩節,祝我的乖老婆和乖乖女兒節日快樂,身體健康啦!
    既然這么高興,就貼一張剛剛照的雯雯百日照好了。
    11.JPG


    評論

    # re: 一個XSLT的變量、參數和模板調用的問題  回復  更多評論   

    2006-03-10 16:06 by NetFetch
    既然結合Xpath來實現他,我看是否可以簡化一些?

    # re: 一個XSLT的變量、參數和模板調用的問題  回復  更多評論   

    2007-06-27 16:59 by zhangcd
    文章寫的好!寶寶很可愛!謝謝!

    # re: 一個XSLT的變量、參數和模板調用的問題  回復  更多評論   

    2008-04-22 12:54 by 54by
    剛開始學XSLT, 試試


    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="Book">
    <xsl:element name="Publication">
    <xsl:attribute name="title" select="@title"/>
    <xsl:attribute name="nbPages" select="sum(chapters/@nbPages)"/>
    <xsl:apply-templates select="chapters[1]"/>
    </xsl:element>
    </xsl:template>
    <xsl:template match="chapters">
    <xsl:param name="str"/>
    <xsl:choose>
    <xsl:when test="not(following-sibling::*)">
    <xsl:attribute name="authors" select="substring(concat($str,' and ',@author),6)"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:apply-templates select="following-sibling::chapters[1]">
    <xsl:with-param name="str" select="concat($str,' and ',@author)"/>
    </xsl:apply-templates>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>
    </xsl:stylesheet>

    # re: 一個XSLT的變量、參數和模板調用的問題[未登錄]  回復  更多評論   

    2008-12-09 19:42 by gordon
    好東西,多謝分享
    主站蜘蛛池模板: 久久国产精品免费一区| 亚洲AV成人无码久久精品老人| 亚洲性无码AV中文字幕| 毛片a级三毛片免费播放| 亚洲另类无码一区二区三区| 国产婷婷高清在线观看免费| 黄色网址免费在线| 国产亚洲精久久久久久无码77777| a毛片全部免费播放| 亚洲啪啪免费视频| a级毛片免费在线观看| 中文字幕免费视频精品一| 亚洲欧洲日产国码一级毛片| 亚洲国产超清无码专区| 成人免费AA片在线观看| 亚洲色成人WWW永久网站| 丰满亚洲大尺度无码无码专线 | 国产亚洲精品AAAA片APP| 全部免费毛片免费播放| 大桥未久亚洲无av码在线| 91精品视频免费| 亚洲最大av资源站无码av网址| 国产男女爽爽爽免费视频| 亚洲免费福利视频| 亚洲福利视频网站| 国产无限免费观看黄网站| 日本免费xxxx| 久久久久亚洲av无码尤物| 久久国产乱子伦精品免费一| 亚洲人成网7777777国产 | 免费福利在线观看| 1024免费福利永久观看网站| 亚洲国产综合在线| 一区二区三区在线观看免费| 无码人妻久久一区二区三区免费 | 久久精品国产亚洲| 在线综合亚洲欧洲综合网站| 8x成人永久免费视频| 精品日韩亚洲AV无码| 日本最新免费网站| 国产成人亚洲精品|