基于多个属性排序节点?
问题描述:
我想根据属性对节点进行排序。假设元素E1中有三个属性A,B和C.我知道一个子组的节点具有相同的属性A和B的值。我怎样才能让这个子组检索具有最大值C的节点?这里棘手的部分是我不知道A的价值。我只知道这个子组共享相同的A值。就像一个双键索引。基于多个属性排序节点?
我正在考虑为每个组的每个底下使用。
例如
<masterNodes>
<Node>
<Element1 A="123" B="LEFT" C="1">
<Element2>...</Element2>
</Node>
<Node>
<Element1 A="123" B="DOWN" C="5">
<Element2>...</Element2>
</Node>
<Node>
<Element1 A="abc" B="RIGHT" C="2">
<Element2>...</Element2>
</Node>
<Node>
<Element1 A="123" B="LEFT" C="3">
<Element2>...</Element2>
</Node>
<Node>
<Element1 A="4XX" B="LEFT" C="4">
<Element2>...</Element2>
</Node>
<Node>
<Element1 A="abc" B="RIGHT" C="1">
<Element2>...</Element2>
</Node>
<Node>
<Element1 A="4XX" B="LEFT" C="5">
<Element2>...</Element2>
</Node>
<Node>
<Element1 A="4XX" B="UP" C="0">
<Element2>...</Element2>
</Node>
</masterNodes>
如何可以只写出来的C为节点A和B的相同值的最大值?
这是我如何构建我的代码。但我从来没有得到它的工作。
<xsl:for-each-group select="/Node/Element1" group-by="@A">
<xsl:for-each select=".[@B='LEFT']">
<xsl:sort select="@C" data-type="number" order="descending"/>
<xsl:if test="position()=1"><xsl:value-of select="@C"/></xsl:if>
</xsl:for-each><xsl:text>
</xsl:text>
<xsl:for-each select=".[@B='RIGHT']">
<xsl:sort select="@C" data-type="number" order="descending"/>
<xsl:if test="position()=1"><xsl:value-of select="@C"/></xsl:if>
</xsl:for-each><xsl:text>
</xsl:text>
<same for other direction>
</xsl:for-each-group>
有什么问题吗?
答
我认为这可以通过使用xsl:key元素对节点进行分组的'muenchian分组'来实现。
首先,定义使用A中的元素1元素的键和B属性
<xsl:key name="Elements" match="Element1" use="concat(@A,@B)"/>
接下来你会使用这个键
<xsl:for-each select="//Element1[generate-id(.) = generate-id(key('Elements', concat(@A,@B))[1])]">
在需要循环throught A的独特组合和B此循环中,您将再次循环,但仅在具有匹配键的元素上,此时按C属性的顺序
<xsl:for-each select="key('Elements', concat(@A,@B))">
<xsl:sort select="@C" order="descending"/>
当你只想要第一个元素,它具有的C属性的最高值,你会再测试位置()
<xsl:if test="position() = 1">
把这个完全给
<xsl:key name="Elements" match="Element1" use="concat(@A,@B)"/>
<xsl:template match="/">
<xsl:for-each select="//Element1[generate-id(.) = generate-id(key('Elements', concat(@A,@B))[1])]">
<xsl:sort select="@C" order="descending"/>
<xsl:for-each select="key('Elements', concat(@A,@B))">
<xsl:sort select="@C" order="descending"/>
<xsl:if test="position() = 1">
(<xsl:value-of select="@A"/>,<xsl:value-of select="@B"/>,<xsl:value-of select="@C"/>)
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
答
如果我的理解规范正确,for-each-group内部的上下文项目被设置为该组的第一个元素。为了排序组,你需要使用current-group()函数。下面的模板似乎工作:
<xsl:template match="/masterNodes">
<xsl:for-each-group select="Node/Element1" group-by="@A">
<xsl:for-each select="current-group()[@B='LEFT']">
<xsl:sort select="@C" data-type="number" order="descending"/>
<xsl:if test="position()=1"><xsl:value-of select="concat(@A, ' ', @B, ' ', @C)"/></xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:for-each select="current-group()[@B='RIGHT']">
<xsl:sort select="@C" data-type="number" order="descending"/>
<xsl:if test="position()=1"><xsl:value-of select="concat(@A, ' ', @B, ' ', @C)"/></xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
</xsl:for-each-group>
</xsl:template>
+1,但我认为OP希望'组通过= “CONCAT(@A,@B)”' – Tomalak 2009-09-30 13:27:26