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属性的排序列表进行编号,但不够流畅,无法到达那里。

提前非常感谢。

使用 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>

最新更新