Как посчитать разные значения в узле?
Как посчитать разные значения в узле в XSLT?
Пример: я хочу посчитать количество существующих стран в узлах страны, в данном случае это будет 3.
<Artists_by_Countries>
<Artist_by_Country>
<Location_ID>62</Location_ID>
<Artist_ID>212</Artist_ID>
<Country>Argentina</Country>
</Artist_by_Country>
<Artist_by_Country>
<Location_ID>4</Location_ID>
<Artist_ID>108</Artist_ID>
<Country>Australia</Country>
</Artist_by_Country>
<Artist_by_Country>
<Location_ID>4</Location_ID>
<Artist_ID>111</Artist_ID>
<Country>Australia</Country>
</Artist_by_Country>
<Artist_by_Country>
<Location_ID>12</Location_ID>
<Artist_ID>78</Artist_ID>
<Country>Germany</Country>
</Artist_by_Country>
</Artists_by_Countries>
4 ответа
Если у вас большой документ, вы, вероятно, захотите использовать "метод Мюнхена", который обычно используется для группировки, чтобы идентифицировать отдельные узлы. Объявите ключ, который индексирует вещи, которые вы хотите считать по значениям, которые различны:
<xsl:key name="artists-by-country" match="Artist_by_Country" use="Country" />
Тогда вы можете получить <Artist_by_Country>
элементы, которые имеют разные страны, использующие:
/Artists_by_Countries
/Artist_by_Country
[generate-id(.) =
generate-id(key('artists-by-country', Country)[1])]
и вы можете посчитать их, завернув это в вызове count()
функция.
Конечно, в XSLT 2.0 это так же просто, как
count(distinct-values(/Artists_by_Countries/Artist_by_Country/Country))
В XSLT 1.0 это не очевидно, но следующее должно дать вам представление о требовании:
count(//Artist_by_Country[not(Location_ID=preceding-sibling::Artist_by_Country/Location_ID)]/Location_ID)
Чем больше элементов в вашем XML, тем дольше это занимает, так как он проверяет каждый предшествующий элемент каждого отдельного элемента.
Попробуйте что-то вроде этого:
count(//Country[not(following::Country/text() = text())])
"Дайте мне количество всех узлов страны без следующей страны с соответствующим текстом"
Интересная часть этого выражения IMO - следующая ось.
Вы также можете удалить первый /text()
и заменить второе на .
Если у вас есть контроль над генерацией xml в первый раз в стране, вы можете добавить к узлу страны атрибут, такой как Different='true', помечать страну как "использованную" и впоследствии не добавлять отдельный атрибут, если вы столкнетесь с этим. опять страна
Вы могли бы тогда сделать
<xsl:for-each select="Artists_by_Countries/Artist_by_Country/Country[@distinct='true']" />