来自以下列表的文件:
<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 :(得分:1)
使用XSLT 3.0(由Saxon 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>