2010-04-21 10 views
6

In che modo XSL può generare un attributo id univoco per ogni elemento in un documento XML utilizzando XSL dove l'ID deve essere numerico? L'XLS di seguito funziona, tranne che gli ID generati sono alfanumerici e ho bisogno di numeri?XSL numerico 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> 

Grazie.

+0

Deve essere XSLT 1.0? Puoi aggiornare a 2.0? – topskip

+0

XSLT 2.0 sarebbe OK. – gregn

+0

Buona domanda (+1). Vedi la mia risposta per una soluzione più efficiente e più semplice. :) –

risposta

3

Cambiare utilizzando il numero() con il livello e il conteggio sembra aver fatto il trucco.

Grazie

<?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

Questo è valido XSLT 1.0, non c'è bisogno di XSLT 2.0 in questo caso. Inoltre, dal momento che nel tuo codice hai cambiato il numero di versione per XML, non XSLT. ;-) – markusk

+0

Markus ben individuato, rimosso 2.0 – gregn

+0

Aggiunto per conservare gli attributi esistenti – gregn

7

È sempre possibile utilizzare:

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

Persone competenti come Michael Kay avvertono che <xsl:number/> non è efficiente (a volte O (N^2)) e dovrebbe essere evitato se possibile.

+0

Anche questo funziona, terrò d'occhio le prestazioni. – gregn

+0

Hai una staffa fuori posto; la soluzione che probabilmente volevi è 'concat (count (ancestor :: node()), '00000000', count (previous :: node()))' –

+0

@ToddMyhre: Grazie per aver notato questo. Corretto ora –