2010-04-21 9 views
6

Как XSL может генерировать уникальный атрибут id для каждого элемента XML-документа с использованием XSL, где идентификатор должен быть числовым? XLS ниже работает, за исключением того, что созданные идентификаторы являются буквенно-цифровыми, и мне нужно числовое?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> 

спасибо.

+0

Должен ли быть XSLT 1.0? Можете ли вы обновить до 2.0? – topskip

+0

XSLT 2.0 будет в порядке. – gregn

+0

Хороший вопрос (+1). См. Мой ответ для более эффективного и простого решения. :) –

ответ

3

Переключение с использованием номера() с уровнем и количеством, похоже, выполнило трюк.

Спасибо

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

Это действительный XSLT 1.0, в этом случае нет необходимости в XSLT 2.0. Точно так же, поскольку в вашем коде вы изменили номер версии для XML, а не XSLT. ;-) – markusk

+0

Хорошо обнаруженный Markusk, 2.0 удален – gregn

+0

Добавлен для сохранения существующих атрибутов – gregn

7

Вы всегда можете использовать:

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

Знающие люди, такие как Майкл Кей предупреждают, что <xsl:number/> не является эффективным (иногда O (N^2)) и этого следует избегать, если это возможно.

+0

Это тоже работает, я буду следить за исполнением. – gregn

+0

У вас есть неуместная скобка; решение, которое вы, скорее всего, хотите, - 'concat (count (ancestor :: node()), '00000000', count (previous :: node()))' –

+0

@ToddMyhre: Спасибо, что заметили это. Исправлено сейчас. –