Sep. 7th, 2005

yorool_gui: (Default)
Разобрался с ним наконец. Раньше только знал, что такой есть, но ни разу не пользовался.
Задача: надо выбрать из XML все возможные значения некоторого поля. Т.е. сделать аналог SQL-ного select distinct. Проблема в том, что в XSLT нет ни переменных, ни массивов и мы не можем просто обойти все узлы, заполняя значениями хеш.
Все, что мы можем -- это обходить все узлы и, если это первый узел с требуемым значением, выводить его.
Пусть XML вот такой
<nodes>
  <node value="a"/>
  <node value="c"/>
  <node value="a"/>
  <node value="b"/>
</nodes>
Простейший способ:
<xsl:for-each select="node[not(preceding-sibling::node/@value=@value)]">
  <xsl:value-of select="@value"/>
</xsl:for-each>
Такой способ тормозит, так как на каждом узле мы просматриваем список узлов назад.
К счастью в xslt есть операток key, создающий индекс узлов.
<xsl:key name="nodes_by_value" match="/*/node" use="@value">
Функция key('nodes_by_value','a') вернет nodeset со всем узлами, у которых атрибут value равен 'a'.
Тогда наш цикл можно записать так:
<xsl:for-each select="node[count( . | key('nodes_by_value',@value)[1] ) =1]">
или так
<xsl:for-each select="node[generate-id(.)=generate-id(key('nodes_by_value',@value)[1] )]">
Так работает гораздо быстрее.
Подробно здесь: http://www.jenitennison.com/xslt/grouping/muenchian.html

Profile

yorool_gui: (Default)
Michael Ilyin

April 2017

S M T W T F S
      1
2 345678
910 1112131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 25th, 2025 06:27 am
Powered by Dreamwidth Studios