Опираясь на ответ Флинна ...
Если у вас есть этот шаблон для родителя (не показан в вашем примере):
<xsl:template match="row-parent">
<xsl:apply-templates select="row">
<xsl:sort select="name(*[1])" />
</xsl:apply-templates>
</xsl:template>
Обратите внимание, что, выбрав «row» вместо значения по умолчанию (все дочерние элементы, включая текстовые узлы), мы избегаем выбора текстовых узлов, содержащих пробелы и нежелательных для нашего вывода.
Затем, чтобы добавить заголовки разделов, шаблон для обработки дочерних элементов использует условное выражение, чтобы определить, является ли это первой строкой раздела:
<xsl:template match="row">
<xsl:variable name="childName" select="name(*[1])"/>
<!-- if this is the first row with an element child of this name -->
<xsl:if test="not(preceding-sibling::row[name(*[1]) = $childName])">
<xsl:value-of select="concat(' ',
translate(substring($childName, 1, 1), $lower, $upper),
substring($childName, 2), ' ')"/>
</xsl:if>
Затем выведите данные для каждой строки этой группы в нужном вам формате:
<xsl:number level="any" count="row[name(*[1]) = $childName]" format=" 1. "
from="row-parent"/>
<xsl:value-of select="normalize-space(*[1])"/>
<xsl:text> </xsl:text>
</xsl:template>
Как обычно, $ lower и $ upper определяются в верхней части шаблона (или таблицы стилей) как
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
И заставить таблицу стилей использовать метод вывода text:
<xsl:output method="text"/>
Вывод вышеуказанной таблицы стилей на ваш ввод (в оболочке <row-parent>
):
Contact
1. some contact details 1
2. some contact details 2
Order
1. some order text 1
2. some order text 2
Payment
1. some payment text 1
В качестве альтернативы и более надежно, вы можете использовать Muenchian grouping : сначала сгруппировать строки по имени дочернего элемента, затем (вывести заголовок для каждой группы и) обработать все строки в группе.