2010-04-21 22 views
6

¿Cómo puede XSL generar un atributo único de identificación para cada elemento en un documento XML utilizando XSL donde el ID debe ser numérico? El XLS siguiente funciona, excepto que los identificadores generados son alfanuméricos y necesito números.XSL numeric generate-id()

<?xml version='1.0' encoding='utf-8'?> 
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
    xmlns:msxsl='urn:schemas-microsoft-com:xslt' exclude-result-prefixes='msxsl'> 
    <xsl:output method='xml' indent='yes'/> 
    <xsl:template match='*'> 
     <xsl:copy> 
     <xsl:attribute name='ElementID'> 
      <xsl:value-of select='generate-id()'/> 
     </xsl:attribute> 
     <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template>  
</xsl:stylesheet> 

Gracias.

+0

¿Tiene que ser XSLT 1.0? ¿Puedes actualizar a 2.0? – topskip

+0

XSLT 2.0 estaría bien. – gregn

+0

Buena pregunta (+1). Vea mi respuesta para una solución más eficiente y simple. :) –

Respuesta

3

La conmutación con el número() con nivel y recuento parece haber hecho el truco.

Gracias

<?xml version='1.0' encoding='utf-8'?> 
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
    xmlns:msxsl='urn:schemas-microsoft-com:xslt' exclude-result-prefixes='msxsl'> 
    <xsl:output method='xml' indent='yes'/> 
    <xsl:template match='*'> 
     <xsl:copy> 
     <xsl:attribute name='ElementID'> 
      <xsl:number level='any' count='*' /> 
     </xsl:attribute> 
     <xsl:copy-of select="@*"/><!--copy of existing all attributes--> 
     <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Esto es XSLT 1.0 válido, sin necesidad de XSLT 2.0 en este caso. Igualmente, ya que en su código ha cambiado el número de versión para XML, no para XSLT. ;-) – markusk

+0

Bien manchado Markusk, 2.0 eliminado – gregn

+0

Añadido para conservar los atributos existentes – gregn

7

Siempre se puede usar:

 concat(count(ancestor::node()), 
      '00000000', 
      count(preceding::node())) 

La gente bien como Michael Kay advierten que <xsl:number/> no es eficiente (a veces O (n^2)) y debe evitarse si es posible.

+0

Eso también funciona, vigilaré el rendimiento. – gregn

+0

Tiene un soporte fuera de lugar; la solución que probablemente desee es 'concat (count (ancestor :: node()), '00000000', count (previous :: node()))' –

+0

@ToddMyhre: Gracias por notar esto. Corregido ahora. –