我想根据属性对节点进行排序。假设元素E1中有三个属性A,B和C.我知道节点的子组具有相同的属性A和B的值。如何让该子组检索具有最大值C的节点?这里棘手的部分是我不知道A的价值是多少。我只知道子组共享相同的A值。就像双键索引一样。
我正在考虑为每个组使用for-each。
例如
<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>
如何只为具有相同A和B值的节点写出C的最大值?
以下是我构建代码的方式。但我从来没有让它发挥作用。
<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>
有什么不对吗?
答案 0 :(得分:1)
如果我正确理解规范,则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 :(得分:0)
我认为这可以通过'muenchian grouping'实现,它使用xsl:key元素对节点进行分组。
首先,使用A和B属性
定义Element1元素的键<xsl:key name="Elements" match="Element1" use="concat(@A,@B)"/>
接下来,您需要使用此键
循环使用A和B的唯一组合<xsl:for-each select="//Element1[generate-id(.) = generate-id(key('Elements', concat(@A,@B))[1])]">
在此循环中,您将再次循环,但仅在具有匹配键的元素上循环,这次按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>