Который, как вы можете видеть, имеет Sport и Sport/Racket Sports дважды :(
К вашему сведению: мне нужно сделать это с помощью XSLT 1.0.
Спасибо
Дэйв
Пожалуйста, в отдельном вопросе объясните, каковы требования/правила формирования вывода (в частности, непонятно, как должны формироваться имена категорий). Я думаю, что можно найти более простое решение и полностью избежать проблемы дублирования. Dimitre Novatchev 11.01.2011
Ах да.. извините, число представляет уровень категории, где 0 - это корневой уровень.. в данном случае "Спорт", а 1 - первый уровень подкатегории, 2 - 2-й уровень подкатегории и т. д. Это обозначение используется по порядку. отправить документ в Solr. Посмотрите на третий вариант в этом письме search.lucidimagination.com/search/document/8a14673728e3a722/ CraftyFella 11.01.2011
Другой способ сделать это без использования функции расширения (но который не обязательно будет таким же эффективным, как использование мюнхианской группировки) - добавить проверку для сравнения предыдущих записей категории, чтобы увидеть, начинаются ли они со строки, о которой вы собираетесь узнать.
В этом фрагменте кода $pos - это параметр, содержащий позицию текущего элемента category, с которым вы в настоящее время сопоставляетесь, а $field-text - это переменная, содержащая текст, который вы собираетесь вывести.
Вот полная таблица стилей XSLT, которая также должна дать вам желаемый результат.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="record">
<add>
<doc>
<xsl:for-each select="category[. != '']">
<xsl:call-template name="split-cats">
<xsl:with-param name="prefix" select="''"/>
<xsl:with-param name="text" select="."/>
<xsl:with-param name="level" select="number(0)"/>
<!-- Position of the current category -->
<xsl:with-param name="pos" select="position()"/>
</xsl:call-template>
</xsl:for-each>
</doc>
</add>
</xsl:template>
<xsl:template name="split-cats">
<xsl:param name="text" select="."/>
<xsl:param name="prefix"/>
<xsl:param name="level" select="0"/>
<xsl:param name="pos"/>
<xsl:choose>
<xsl:when test="contains($text, '/')">
<xsl:variable name="field-text" select="concat($prefix, substring-before($text, '/'))"/>
<!-- Test no previous category begins with the text we are about to output -->
<xsl:if test="not(/record/category
[. != '']
[position() < $pos]
[substring(., 1, string-length($field-text)) = $field-text])">
<field>
<xsl:attribute name="name">
<xsl:text>category_</xsl:text>
<xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:value-of select="$field-text"/>
</field>
</xsl:if>
<xsl:call-template name="split-cats">
<xsl:with-param name="prefix" select="concat($prefix, concat(substring-before($text, '/'), '/'))"/>
<xsl:with-param name="text" select="substring-after($text, '/')"/>
<xsl:with-param name="level" select="$level + 1"/>
<xsl:with-param name="pos" select="$pos"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="field-text" select="concat($prefix, $text)"/>
<!-- Test no previous category begins with the text we are about to output -->
<xsl:if test="not(/record/category
[. != '']
[position() < $pos]
[substring(., 1, string-length($field-text)) = $field-text])">
<field>
<xsl:attribute name="name">
<xsl:text>category_</xsl:text>
<xsl:value-of select="$level"/>
</xsl:attribute>
<xsl:value-of select="$field-text"/>
</field>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>