2016-05-12 118 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