2009-09-30 138 views
1

我想根据属性对节点进行排序。假设元素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>&#xD;</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>&#xD;</xsl:text> 
    <same for other direction> 
</xsl:for-each-group> 

有什么问题吗?

回答

0

我认为这可以通过使用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(&apos;Elements&apos;, 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> 
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>&#xD;</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>&#xD;</xsl:text> 
    </xsl:for-each-group> 

</xsl:template> 
+0

+1,但我认为OP希望'组通过= “CONCAT(@A,@B)”' – Tomalak 2009-09-30 13:27:26