2016-05-12 4 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 (как поддерживается 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> 
+0

Большое вам спасибо! Из любопытства, была ли какая-либо практическая альтернатива XSLT 2.0? – Robin

+0

Большое вам спасибо! – Robin

+0

Wow, 3.0, 2.0, и 1.0 - trifecta хороших ответов! – kjhughes

Смежные вопросы