Вы, вероятно, хотите думать об этом в два этапа; сначала выполните преобразование, которое разбивает эти атрибуты значений, а затем подсчитать их довольно просто.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@value">
<xsl:call-template name="breakdown">
<xsl:with-param name="itemlist" select="substring-before(substring-after(.,'['),']')" />
</xsl:call-template>
</xsl:template>
<xsl:template name="breakdown">
<xsl:param name="itemlist" />
<xsl:choose>
<xsl:when test="contains($itemlist,',')">
<xsl:element name="value">
<xsl:value-of select="normalize-space(substring-before($itemlist,','))" />
</xsl:element>
<xsl:call-template name="breakdown">
<xsl:with-param name="itemlist" select="substring-after($itemlist,',')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:element name="value">
<xsl:value-of select="normalize-space($itemlist)" />
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Помимо шаблона «поймать все» внизу, он собирает любые атрибуты значений в заданном вами формате и разбивает их на отдельные элементы (как подэлементы элемента «metadata_valuelist»), например:
...
<metadata_valuelist>
<value>SampleItem1</value>
<value>SampleItem2</value>
</metadata_valuelist>
...
Выбор 'substring-before / substring-after, который вы видите рядом с верхней частью, удаляет' ['и'] 'перед передачей его шаблону' breakdown '. Этот шаблон будет проверять, есть ли запятая в параметре 'itemlist', и если он есть, он выплевывает текст перед ним как содержимое элемента 'value', а затем рекурсивно вызывает себя с остальной частью списка. Если в параметре не было запятой, он просто выводит все содержимое параметра в виде элемента «значение».
Тогда просто запустите это:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:key name="itemvalue" match="value" use="text()" />
<xsl:template match="/">
<xsl:value-of select="count(//value[generate-id(.) = generate-id(key('itemvalue',.)[1])])" />
</xsl:template>
</xsl:stylesheet>
в XML, который вы получите от первого преобразования, и он просто выдаст одно значение в виде текстового вывода, которое сообщит вам, сколько у вас различных значений.
РЕДАКТИРОВАТЬ: Я, вероятно, должен указать, что это решение делает несколько предположений о вашем вводе:
- Нигде в документе нет атрибутов с именем 'value'; если таковые имеются, вы можете изменить соответствие @value, чтобы выделить их специально.
- Нет нигде в документе элементов с именем 'value'; поскольку первое преобразование создает их, второе не сможет различить два. Если есть, вы можете заменить две строки
<xsl:element name="value">
на имя элемента, которое еще не использовалось.
- Содержимое атрибута @value всегда начинается с «[» и заканчивается «]», и в списке нет символов «]»; если есть, функция 'substring-before' будет отбрасывать все после первого ']', а не только ']' в конце.
- В названиях предметов, которые вы хотите сосчитать, нет запятых, например, [SampleItem1, "Sample2,3"]. Если они есть, «Sample2» и «3» будут рассматриваться как отдельные элементы.