我试图遍历每个"目的地"根据他们的旅行分组' IDS。也就是说,包含完全相同行程(由其id确定)的所有目的地应该是一次迭代。
在下面的示例XML中,两个第一个目的地每个包含四次旅行。目的地的四次旅行" 1" /"巴哈马"与目的地相同的四次旅行" 2" /"夏威夷"。第三个目的地包含另一组旅行。我想在这里进行两次迭代:第一次迭代包含目标" 1"和" 2" (因为目的地的所有旅行" 1"在目的地" 2"反过来),第二次迭代包含目的地" 3"。
如果 目的地" 2"没有id =" 4"的行程,我希望它能进行三次迭代:每个目的地一次,因为它们都不包含完全相同的行程。
数据的结构或多或少与此类似,但在另一个上下文和更多数据中。 Sooo,不要过分关注数据的结构。遗憾的是,改变结构不是一种选择,因为我无法控制数据。
<destinations>
<destination>
<key>1</key>
<location>Bahamas</location>
<tags>
<tag>summer</tag>
<tag>beach</tag>
<tag>surfing</tag>
</tags>
<easy-trips>
<trip>
<id>1</id>
</trip>
<trip>
<id>2</id>
</trip>
</easy-trips>
<experienced-trips>
<trip>
<id>3</id>
</trip>
<trip>
<id>4</id>
</trip>
<experienced-trips>
</destination>
<destination>
<key>2</key>
<location>Hawaii</location>
<tags>
<tag>summer</tag>
<tag>beach</tag>
<tag>surfing</tag>
</tags>
<easy-trips>
<trip>
<id>1</id>
</trip>
<trip>
<id>2</id>
</trip>
</easy-trips>
<experienced-trips>
<trip>
<id>3</id>
</trip>
<trip>
<id>4</id>
</trip>
<experienced-trips>
</destination>
<destination>
<key>3</key>
<location>Rio</location>
<tags>
<tag>big city life</tag>
<tag>samba</tag>
</tags>
<easy-trips>
<trip>
<id>8</id>
</trip>
<trip>
<id>9</id>
</trip>
</easy-trips>
<experienced-trips>
<trip>
<id>10</id>
</trip>
<trip>
<id>11</id>
</trip>
<experienced-trips>
</destination>
</destinations>
到目前为止我尝试了什么
<xsl:for-each-group select="/destinations/destination" group-by="current()//id">
当我在每个目的地只有一次旅行时,在开始时表现出了良好的承诺。添加更多行程时,这将无效。在上面的示例中,它将前两个目的地作为一个组循环四次(每个目标共有一个),然后继续前往目的地&#34; 3&#34; /&#34;里约&#34;。
还考虑了Muenchian方法,但似乎没有比#34; for-each-group&#34;尝试。
有解决方案吗?
有关如何解决此问题的任何想法都是 高度 赞赏!提前,谢谢你的时间和帮助! : - )
---编辑---
向示例XML(标记)添加了更多数据。作为数据结构的相关性,包含完全相同行程的目标将始终具有相同的标记。像目的地&#34; 1&#34;和&#34; 2&#34;在示例中。
所需的输出
<tagCollections>
<tagCollection>
<tag>summer</tag>
<tag>beach</tag>
<tag>surfing</tag>
</tagCollection>
<tagCollection>
<tag>big city life</tag>
<tag>samba</tag>
</tagCollection>
</tagCollections>
答案 0 :(得分:0)
我认为您希望使用<xsl:for-each-group select="/destinations/destination" group-by="string-join(.//id, '+')">
之类的代码在Xslt 2.0中计算复合分组键。我使用的加号只是一个例子,使用从未在id值中使用的任何字符。
当前的建议假定id是有序的,如果没有,你需要首先编写一个函数来执行排序,然后在group-by中调用。
我添加了一个XSLT 3.0示例(可以与Saxon 9的商业版本一起运行),它展示了如何使用函数对序列进行排序以及如何在group-by
中使用它:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:output indent="yes"/>
<xsl:function name="mf:sort">
<xsl:param name="input-sequence" as="item()*"/>
<xsl:perform-sort select="$input-sequence">
<xsl:sort select="."/>
</xsl:perform-sort>
</xsl:function>
<xsl:template match="destinations">
<tagCollections>
<xsl:for-each-group select="/destinations/destination"
group-by="string-join(mf:sort(.//id/xs:integer(.))!string(), '+')">
<tagCollection>
<xsl:copy-of select="tags/tag"/>
</tagCollection>
</xsl:for-each-group>
</tagCollections>
</xsl:template>
</xsl:stylesheet>
应用于输入样本
<destinations>
<destination>
<key>1</key>
<location>Bahamas</location>
<tags>
<tag>summer</tag>
<tag>beach</tag>
<tag>surfing</tag>
</tags>
<easy-trips>
<trip>
<id>1</id>
</trip>
<trip>
<id>2</id>
</trip>
</easy-trips>
<experienced-trips>
<trip>
<id>3</id>
</trip>
<trip>
<id>4</id>
</trip>
</experienced-trips>
</destination>
<destination>
<key>2</key>
<location>Hawaii</location>
<tags>
<tag>summer</tag>
<tag>beach</tag>
<tag>surfing</tag>
</tags>
<easy-trips>
<trip>
<id>4</id>
</trip>
<trip>
<id>3</id>
</trip>
</easy-trips>
<experienced-trips>
<trip>
<id>2</id>
</trip>
<trip>
<id>1</id>
</trip>
</experienced-trips>
</destination>
<destination>
<key>3</key>
<location>Rio</location>
<tags>
<tag>big city life</tag>
<tag>samba</tag>
</tags>
<easy-trips>
<trip>
<id>8</id>
</trip>
<trip>
<id>9</id>
</trip>
</easy-trips>
<experienced-trips>
<trip>
<id>10</id>
</trip>
<trip>
<id>11</id>
</trip>
</experienced-trips>
</destination>
</destinations>
我得到了输出
<tagCollections>
<tagCollection>
<tag>summer</tag>
<tag>beach</tag>
<tag>surfing</tag>
</tagCollection>
<tagCollection>
<tag>big city life</tag>
<tag>samba</tag>
</tagCollection>
</tagCollections>
使用XSLT 2.0当然也可以,表达式稍长一些:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:output indent="yes"/>
<xsl:function name="mf:sort">
<xsl:param name="input-sequence" as="item()*"/>
<xsl:perform-sort select="$input-sequence">
<xsl:sort select="."/>
</xsl:perform-sort>
</xsl:function>
<xsl:template match="destinations">
<tagCollections>
<xsl:for-each-group select="/destinations/destination"
group-by="string-join(for $n in mf:sort(.//id/xs:integer(.)) return string($n), '+')">
<tagCollection>
<xsl:copy-of select="tags/tag"/>
</tagCollection>
</xsl:for-each-group>
</tagCollections>
</xsl:template>
</xsl:stylesheet>