Я пытаюсь показать XML «2D-список» следующим образом:
<list1>
<list2>a</list2>
<list2>b</list2>
<list2>c</list2>
<list2>d</list2>
</list1>
<list1>
<list2>e</list2>
<list2>f</list2>
<list2>g</list2>
<list2>h</list2>
<list2>i</list2>
<list2>j</list2>
</list1>
И я хотел бы, чтобы это отображалось так:
01 a
02 b
03 c
04 d
05 e
06 f
07 g
08 h
09 i
10 j
Сначала я думал, что переменная xsl: должна быть вне двух переменных for-each и увеличиваться, но переменные неизменяемы. Как это может быть сделано?
заранее спасибо





Здесь не нужно xsl:variable или даже больше одного xsl:for-each (или xsl:apply-templates). Вы можете просто выбрать все элементы list2 сразу, а затем использовать position() для получения нумерации, потому что position() основан на положении узла в наборе выбранных узлов, а не на положении в дереве документа.
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "2.0">
<xsl:output method = "text" />
<xsl:template match = "/*">
<xsl:apply-templates select = "list1/list2" />
</xsl:template>
<xsl:template match = "list2">
<xsl:value-of select = "concat(format-number(position(), '00'), ' ', ., ' ')" />
</xsl:template>
</xsl:stylesheet>
Это предполагает, что ваш XML правильно сформирован, и все элементы list1 находятся в одном родительском элементе.
См. http://xsltfiddle.liberty-development.net/gWvjQf9
Еще один возможный способ добиться этого:
<?xml version = "1.0" encoding = "utf-8"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output method = "xml" indent = "yes" />
<xsl:strip-space elements = "*" />
<xsl:template match = "/root">
<xsl:variable name = "items" select = "//list1/list2" />
<xsl:for-each select = "list1">
<xsl:for-each select = "list2">
<xsl:variable name = "id" select = "generate-id()" />
<xsl:for-each select = "$items">
<xsl:if test = "generate-id() = $id">
<xsl:value-of select = "position()" />
<xsl:value-of select = "concat(' ',.)" />
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
http://xsltransform.net/eieE3Q8/1
Очень неосознанно сложный ответ.
<xsl:template match = "/">
<xsl:apply-templates select = "list1/list2"/>
</xsl:template>
<xsl:template match = "//list2">
<xsl:value-of select = "concat(format-number(position(), '00'), ' ', ., ' ')" />
</xsl:template>
Этот ответ неверен. Первое правило, соответствующее корню документа, не требуется. Второе правило не дает желаемого результата: positionфункция относится к списку контекстов, в данном случае ко всем родственным list2 элементам каждого list1 отца. Короче говоря, перечисление будет перезапущено. Заезд утилиты-онлайн.info/xsltransformation/…
Я удивлен, что никто не упомянул об использовании xsl:number. Это то, что я обычно использую, когда мне нужно пронумеровать что-то вроде списка.
Пример...
XML-ввод
<doc>
<list1>
<list2>a</list2>
<list2>b</list2>
<list2>c</list2>
<list2>d</list2>
</list1>
<list1>
<list2>e</list2>
<list2>f</list2>
<list2>g</list2>
<list2>h</list2>
<list2>i</list2>
<list2>j</list2>
</list1>
</doc>
XSLT 1.0 (Работает и в других версиях.)
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text"/>
<xsl:strip-space elements = "*"/>
<xsl:template match = "list2">
<xsl:number level = "any" format = "01 "/>
<xsl:value-of select = "concat(.,'
')"/>
</xsl:template>
</xsl:stylesheet>
Выход
01 a
02 b
03 c
04 d
05 e
06 f
07 g
08 h
09 i
10 j
Рабочий пример: http://xsltfiddle.liberty-development.net/gWvjQfa/1
С возвращением, @Alejandro!
Правильно указывает на концепцию контекстный список для функции
position.