所以我有这个XML:
<Main>
<TB>
--> some elements - not relevant
<Area>
<Type>A</Type>
<Street>
<Position>5</Position>
<House>
--> some elements
</House>
</Street>
<Street>
<Position>5</Position>
<Block>
--> some elements
</Block>
</Street>
<Street>
<Position>6</Position>
<House>
--> some elements
</House>
</Street>
<Street>
<Position>6</Position>
<Block>
--> some elements
</Block>
</Street>
</Area>
<Area>
<Type>B</Type>
--> same structure but with several repetitions of Position 7 and 8.
</Area>
</TB>
</Main>我想这样排序:
<Area>
<Type>A</Type>
<Street>
<Position>5</Position>
<House>
--> some elements
</House>
<Block>
--> some elements
</Block>
</Street>
<Street>
<Position>6</Position>
<House>
--> some elements
</House>
<Block>
--> some elements
</Block>
</Street>
</Area>
<Area>
<Type>B</Type>
--> same structure for Position 7 and 8.
</Area>我正在使用这个XSLT来转换它:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes" />
<xsl:key name="streetByPosition" match="Street" use="Position" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<!-- for the first Street in each Position -->
<xsl:template match="Street[generate-id() =
generate-id(key('streetByPosition', Position)[1])]">
<Street>
<!-- copy in the Position element once only -->
<xsl:apply-templates select="Position" />
<!-- copy in all sub-elements except Position from all matching Streets-->
<xsl:apply-templates select="
key('streetByPosition', Position)/*[not(self::Position)]" />
</Street>
</xsl:template>
<!-- ignore all other Street elements -->
<xsl:template match="Street" />
</xsl:stylesheet>排序完全正常。但是如果我在不同的Type中有重复的Position数,那么我会得到所有的House和Block,排列在第一个Type中,其中我有重复的Position数。例如:
<Area>
<Type>A</Type>
<Street>
<Position>5</Position>
<House>
--> some elements
</House>
</Street>
<Street>
<Position>5</Position>
<Block>
--> some elements
</Block>
</Street>
....
<Area>
<Type>B</Type>
<Street>
<Position>5</Position>
<House>
--> some elements
</House>
</Street>然后,Type B中Position 5下的元素将从那里移动到TypeA中的Position 5下。我不想这样。我希望房屋和街区被安排,但留在他们自己的类型和区域。
有没有人能给我提供一个解决方案,告诉我如何修改我的XSLT才能解决这个问题?
附注:由于简化的原因,XML标记的名称被更改。而且我不能使用xslt-2.0,因为我的编辑器不支持它。
发布于 2013-06-14 21:49:20
为此,您需要一个复合键,它是标识您的组的所有值的串联,在本例中为(父元素的)类型和位置
<xsl:key name="streetByPosition" match="Street" use="concat(../Type, '|', Position)" />然后,您可以按常规方式使用密钥
key('streetByPosition', concat(../Type, '|', Position))尝试以下XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes" />
<xsl:key name="streetByPosition" match="Street" use="concat(../Type, '|', Position)" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<!-- for the first Street in each Position -->
<xsl:template match="Street[generate-id() =
generate-id(key('streetByPosition', concat(../Type, '|', Position))[1])]">
<Street>
<!-- copy in the Position element once only -->
<xsl:apply-templates select="Position" />
<!-- copy in all sub-elements except Position from all matching Streets-->
<xsl:apply-templates select="
key('streetByPosition', concat(../Type, '|', Position))/*[not(self::Position)]" />
</Street>
</xsl:template>
<!-- ignore all other Street elements -->
<xsl:template match="Street" />
</xsl:stylesheet>唯一要注意的是,连接中的“”字符可以是您喜欢的任何字符,只要它不出现在管道类型和Position元素中,以确保这类元素的两个不同组合不会产生相同的键。
https://stackoverflow.com/questions/17109793
复制相似问题