XSLT: Distinct значения из не очень "плоской структуры" XML

cat_crash

Новичок
XSLT: Distinct значения из не очень "плоской структуры" XML

Привет, all

Столкнулся с задачкой которую уже неделю не могу победить, поэтому взываю вселенский разум на помощь:
Дано: XML + XSTL шаблон. Надо выбрать из него все уникальные значения городов.
PHP:
<root>
<item id="0">
	<id>73</id>
		[B]<departures>
			<id>1</id>
			<name>Москва</name>
		</departures>[/B]
	<name>Коста Брава(Барселона)</name>
</item>

<item id="1">
	<id>78</id>
		[B]<departures>
			<id>1</id>
			<name>Москва</name>
		</departures>[/B]
	<name>Тенерифе</name>
	<regions>
		<item id="0">
			<id>211</id>
			<name>Мадрид</name>
		</item>

		<item id="1">
			<id>359</id>
			<name>Тенерифе</name>
		</item>
	</regions>
</item>
<item id="7">
	<id>130</id>
		[B]<departures>
			<id>2</id>
			<name>Санкт-Петербург</name>
		</departures>[/B]
	<name>Испания</name>
</item>
</root>
Суть проблемы - в ветке DEPARTURES лежат города из которых возможен вылет и они повторяются. Хотелось бы сделать <select> в котором были бы только уникальные значения городов.

Нашел я некий Set:distinct но почему то он не сильно мне помогает:
PHP:
<xsl:for-each select="item">
	<xsl:call-template name="distinct">
		<xsl:with-param name="nodes" select="departures/id"/>
	</xsl:call-template>
</xsl:for-each>

<xsl:template name="distinct">
	  <xsl:param name="nodes" select="/.."/>
	  <xsl:param name="distinct" select="/.."/>
	  <xsl:choose>
		<xsl:when test="$nodes">
		  <xsl:call-template name="distinct">
		  <xsl:with-param name="distinct" select="$distinct | $nodes[1][not(. = $distinct)]"/>
		  <xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
		  </xsl:call-template>
		</xsl:when>
		<xsl:otherwise>
		  <xsl:apply-templates select="$distinct" mode="distinct"/>
		</xsl:otherwise>
	  </xsl:choose>
	</xsl:template>

	<xsl:template match="node()|@*" mode="distinct">
		<option value="{../id}"><xsl:value-of select="../name"/></option>
	</xsl:template>
 

slach

Новичок
http://www.shwaps.com/articles/xsl_distinct_nodes.html
либо через оси

либо через группировку мюнха
http://xpoint.ru/know-how/XML/XSLT/CookBook/Grouping

если кратко для твоего случая
делаем
<xsl:key name="city" match="/item/departures/name"use="name"/>

далее

<xsl:apply-templates
select="item[generate-id(.) = generate-id(key('name',@group))]"
/>


тебе надо понять что XSLT оперирует ДЕРЕВЬЯМИ... и это не процедурный и не императивный... а ДЕКЛАРАТИВНЫЙ язык.. т.е. ты только описываешь правила... а по этим правилам XSLT транформатор бегает по исходному дереву...и строит новое...
 

cat_crash

Новичок
Автор оригинала: slach
http://www.shwaps.com/articles/xsl_distinct_nodes.html
либо через оси

либо через группировку мюнха
http://xpoint.ru/know-how/XML/XSLT/CookBook/Grouping

если кратко для твоего случая
делаем
<xsl:key name="city" match="/item/departures/name"use="name"/>

далее

<xsl:apply-templates
select="item[generate-id(.) = generate-id(key('name',@group))]"
/>


тебе надо понять что XSLT оперирует ДЕРЕВЬЯМИ... и это не процедурный и не императивный... а ДЕКЛАРАТИВНЫЙ язык.. т.е. ты только описываешь правила... а по этим правилам XSLT транформатор бегает по исходному дереву...и строит новое...
Привет.
Хочу выразить благодарность за то что подтолкнул на мысль. Самым простым решение оказалось использовать оси (взято из примера который кинул slach:
PHP:
<xsl:for-each select="item/destination">  
 <xsl:if test="not(preceding::name = name)">
  <xsl:value-of select="name" disable-output-escaping="yes"/>
 </xsl:if>
</xsl:for-each>
 

FB3

Новичок
cat_crash
Это самое простое решение не будет быстрым. Лучше с ключами.
 
Сверху