2009-06-18 16 views
1
<statisticItems> 
    <statisticItem id="1" frontendGroupId="2336" caseId="50264" /> 
    <statisticItem id="2" frontendGroupId="2336" caseId="50264" /> 
    <statisticItem id="3" frontendGroupId="2337" caseId="50265" /> 
    <statisticItem id="4" frontendGroupId="2337" caseId="50266" /> 
    <statisticItem id="5" frontendGroupId="2337" caseId="50266" /> 
</statisticItems> 

<?xml version="1.0" encoding="utf-8"?> 
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" omit-xml-declaration="yes"/> 

    <xsl:key name="statistic-by-frontendGroupId" match="statisticItem" use="@frontendGroupId" /> 

    <xsl:for-each select="statisticItems/statisticItem[count(.|key('statistic-by-frontendGroupId', @frontendGroupId)[1]) = 1]"> 
     <xsl:value-of select="@frontendGroupId"/> 
    </xsl:for-each> 

私が行ったことは、すべてのdistend frontendGroupIdsを通過することです。私が今したいことは、各distend frontendGroupIdのすべてのdistict caseIdsのカウントを行うことですが、私はその作業を行うことはできません。誰かがここで私を助けることができますPLZ?XSlt個別の選択/グループ

答えて

0

恐ろしい 'MUENCHIAN'メソッドでソートしようとしています。私はそれほど混乱しないと思っていましたので、自分の方法を試しました。

これは1つではなく2つの変換を使用します。

最初は、あなたのグループの要件に基づいて右の順にデータをソートする - 私は

(あなたがここで役立つかどうかを尋ねる)この説明からそれを残しておきますので、あなたのサンプルデータが正しい順序で既にあります

第2の変換は、次の1つのノードを比較することにより、簡単にグループ分けん:この方法で

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 


    <xsl:template match="statisticItems"> 
     <groupedItem> 
      <xsl:apply-templates select="statisticItem"></xsl:apply-templates> 
     </groupedItem> 
    </xsl:template> 

    <xsl:template match="statisticItem"> 
     <xsl:choose> 

      <xsl:when test="position()=1"> 
       <xsl:apply-templates select="@frontendGroupId" /> 
      </xsl:when> 

      <xsl:when test="@frontendGroupId!=preceding-sibling::statisticItem[1]/@frontendGroupId"> 
       <xsl:apply-templates select="@frontendGroupId" /> 
      </xsl:when> 

     </xsl:choose> 

     <xsl:apply-templates select="@caseId" /> 


    </xsl:template> 

<xsl:template match="@frontendGroupId"> 
    <group> 
     <xsl:variable name="id" select="." ></xsl:variable> 
     <xsl:attribute name="count"> 
      <xsl:value-of select="count(//statisticItem/@frontendGroupId[.=$id])"/> 
     </xsl:attribute>   
     <xsl:value-of select="." /> 
    </group> 
</xsl:template> 

    <xsl:template match="@caseId"> 
     <value> 
      <xsl:value-of select="." /> 
     </value> 
    </xsl:template> 

</xsl:stylesheet> 

あなたは深いいくつかのグループに行くと、まだ保守性のコードを持つことができます。

+1

「何か私は混乱していることが分かりましたが、それは試してみる価値がありません」なんて奇妙な態度。 – Tomalak

+0

あなたは正しく私の文法が間違っています - 私は試してみました - 私はサーバーレベルをグループ化する必要がありました(正しく覚えていれば4または5)。私はそれを働かせましたが、キーの定義は非常に混乱していました。特に、入れ子にされたグループが深くなるときです。しかし、私が上に示してみた2つのパスの方法は、はるかに説明して読みやすくなります – Adrian

+0

私の答えを読むことをお勧めします:http:// stackoverflow。com/questions/948218/xslt-3-level-grouping-on-attributes - 多分それはあなたに役立ちます:-) – Tomalak

6

あなたが接近していた:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="text" /> 

    <xsl:key 
    name="statistic-by-frontendGroupId" 
    match="statisticItem" 
    use="@frontendGroupId" 
    /> 

    <xsl:template match="statisticItems"> 
    <xsl:for-each select=" 
     statisticItem[ 
     count(
      . | key('statistic-by-frontendGroupId', @frontendGroupId)[1] 
     ) = 1 
     ] 
    "> 
     <xsl:value-of select="@frontendGroupId"/> 
     <xsl:value-of select="' - '"/> 
     <!-- simple: the item count is the node count of the key --> 
     <xsl:value-of select=" 
     count(
      key('statistic-by-frontendGroupId', @frontendGroupId) 
     ) 
     "/> 
     <xsl:value-of select="'&#10;'"/> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

これは、その結果:

 
2336 - 2 
2337 - 3 

EDIT - ああ、私はあなたが、グループ内の個別のカウントをしたい参照してください。これは次のようになります。

<!-- the other key from the above solution is still defined --> 

<xsl:key 
    name="kStatisticItemByGroupAndCase" 
    match="statisticItem" 
    use="concat(@frontendGroupId, ',', @caseId)" 
/> 

<xsl:template match="statisticItems"> 
    <xsl:for-each select=" 
    statisticItem[ 
     count(
     . | key('kStatisticItemByGroup', @frontendGroupId)[1] 
    ) = 1 
    ] 
    "> 
    <xsl:value-of select="@frontendGroupId"/> 
    <xsl:value-of select="' - '"/> 
    <xsl:value-of select=" 
     count(
     key('kStatisticItemByGroup', @frontendGroupId)[ 
      count(
      . | key('kStatisticItemByGroupAndCase', concat(@frontendGroupId, ',', @caseId))[1] 
     ) = 1 
     ] 
    ) 
    "/> 
    <xsl:value-of select="'&#10;'"/> 
    </xsl:for-each> 
</xsl:template> 

少し恐ろしいです(確かに)。これは、出力:

 
2336 - 1 
2337 - 2 

コア式:

count(
    key('kStatisticItemByGroup', @frontendGroupId)[ 
    count(
     . | key('kStatisticItemByGroupAndCase', concat(@frontendGroupId, ',', @caseId))[1] 
    ) = 1 
    ] 
) 

がに沸く:

次の条件を満たして「key('kStatisticItemByGroup', @frontendGroupId)」からノードカウント:彼らは、それぞれの最初のです」 kStatisticItemByGroupAndCase "グループ。

よく見ると、これはすでに行っていることよりも複雑ではありません。 :-)


EDIT:1つの最後のヒント。それは「count(.|something) = 1」アプローチよりも多くのノードの平等を強調しているので個人的に、私は、上記の式よりも、この多くのより表現見つける:

count(
    key('kStatisticItemByGroup', @frontendGroupId)[ 
    generate-id() 
    = 
    generate-id(
     key('kStatisticItemByGroupAndCase', concat(@frontendGroupId, ',', @caseId))[1] 
    ) 
    ] 
) 

結果は同じです。

関連する問題