2016-05-12 117 views
1

從一個文件的值的編號的屬性,如下面的列表:XSLT - 創建基於另一屬性

<list> 
    <city ref="Paris">Paris</city> 
    <city ref="Rome">Rome</city> 
    <city ref="NYC">New York</city> 
    <city ref="Lisboa">Lisboa</city> 
    <city ref="Lisboa">Lisbon</city> 
    <city ref="Lisboa">Lisbonne</city> 
    <city ref="NYC">The Big Apple</city> 
</list> 

我想獲得該列表的一個副本,其中衍生自添加的數字屬性在@ref屬性(最好是按字母順序排列),對於喜歡的輸出:

<list> 
    <city ref="Paris" id="3">Paris</city> 
    <city ref="Rome" id="4">Rome</city> 
    <city ref="NYC" id="2">New York</city> 
    <city ref="Lisboa" id="1">Lisboa</city> 
    <city ref="Lisboa" id="1">Lisbon</city> 
    <city ref="Lisboa" id="1">Lisbonne</city> 
    <city ref="NYC" id="2">The Big Apple</city> 
</list> 

我想有使用<xsl:key>數點我@ref屬性的排序列表的方式,但我不夠流利得到那裏。

非常感謝提前。

+0

你可以使用XSLT 2.0嗎? –

回答

1

使用XSLT 3.0(由撒克遜9.7所支持的)是一樣容易

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" 
    exclude-result-prefixes="xs math" 
    version="3.0"> 

    <xsl:variable name="cities" select="sort(distinct-values(/list/city/@ref))"/> 

    <xsl:mode on-no-match="shallow-copy"/> 

    <xsl:template match="city/@ref"> 
     <xsl:copy/> 
     <xsl:attribute name="id" select="index-of($cities, .)"/> 
    </xsl:template> 

</xsl:stylesheet> 

隨着XSLT 2.0我們可以使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:variable name="cities" as="xs:string*"> 
     <xsl:perform-sort select="distinct-values(/list/city/@ref)"> 
      <xsl:sort select="."/> 
     </xsl:perform-sort> 
    </xsl:variable> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* , node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="city/@ref"> 
     <xsl:copy/> 
     <xsl:attribute name="id" select="index-of($cities, .)"/> 
    </xsl:template> 

</xsl:stylesheet> 

最後用XSLT 1.0以上 「翻譯」 成

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common" 
    exclude-result-prefixes="exsl" 
    version="1.0"> 

    <xsl:key name="city" match="city" use="@ref"/> 

    <xsl:variable name="cities-rtf"> 
     <xsl:for-each select="/list/city[generate-id() = generate-id(key('city', @ref)[1])]"> 
      <xsl:sort select="@ref"/> 
      <city id="{position()}" ref="{@ref}"/> 
     </xsl:for-each> 
    </xsl:variable> 

    <xsl:variable name="cities" select="exsl:node-set($cities-rtf)/city"/> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="city/@ref"> 
     <xsl:copy/> 
     <xsl:attribute name="id"> 
      <xsl:value-of select="$cities[@ref = current()]/@id"/> 
     </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 
+0

非常感謝! 出於好奇,XSLT 2.0會不會有任何可行的選擇? – Robin

+0

非常感謝! – Robin

+0

哇,3.0,2.0和1.0 - 一個好答案的三連勝! – kjhughes