2009-06-18 14 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> 

Was ich bisher getan habe, ist durch alle distinguierten FrontendGroupIds zu gehen. Was ich jetzt tun möchte, ist eine Zählung aller distinct caseIds für jede disct FrontendGroupId, aber ich kann nicht scheinen, dass das funktioniert. Kann mir hier jemand helfen?Xslt distinct select/Gruppe von

Antwort

0

Sie versuchen, über die gefürchtete "MÜNCHIAN" -Methode zu sortieren - etwas, das ich so verwirrend gefunden habe, dass es keinen Versuch wert ist - also habe ich meine eigene Methode ausgearbeitet.

Es verwendet zwei Transformationen anstelle von eins.

Die ersten Sorten die Daten in der richtigen Reihenfolge auf der Grundlage Ihrer Gruppierung Anforderungen - Ihre Datenprobe bereits in der richtigen Reihenfolge ist, so habe ich es aus dieser Erklärung verlassen werden (fragen Sie, wenn Sie hier wollen helfen)

die zweite Transformation macht die Gruppierung einfach von einem Knoten zum nächsten Vergleich:

<?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> 

Mit dieser Methode können Sie mehrere Gruppen tief und immer noch haben wartbaren Code gehen.

+1

"etwas, das ich so verwirrend gefunden habe, ist es nicht wert zu versuchen" Was für eine seltsame Einstellung. – Tomalak

+0

Sie richtig meine Grammatik ist falsch - ich habe es versucht - viel, ich musste mehrere Ebenen (4 oder 5 wenn ich mich richtig erinnere) gruppieren. Ich habe es funktioniert, aber die wichtigsten Definitionen waren sehr verwirrend, besonders wenn die verschachtelten Gruppierungen tief werden. Aber die Zwei-Pass-Methode, die ich versucht habe, oben zu zeigen, ist viel einfacher zu erklären und zu lesen – Adrian

+0

Ich empfehle, meine Antwort zu lesen: http: // stackoverflow.com/questions/948218/xslt-3-level-grouping-on-attribute - vielleicht hilft es dir :-) – Tomalak

6

Sie waren in der Nähe:

<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> 

Daraus ergibt sich:

 
2336 - 2 
2337 - 3 

EDIT - Oh, ich sehe, Sie die Distinct Count innerhalb der Gruppe werden soll. Dies wäre:

<!-- 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> 

Was (zugegebenermaßen) ein bisschen beängstigend aussieht. Es gibt:

 
2336 - 1 
2337 - 2 

Der Kern expression:

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

läuft darauf hinaus:

Zähle die Knoten von "key('kStatisticItemByGroup', @frontendGroupId)", die die folgende Bedingung erfüllen: Sie sind die ersten in ihren jeweiligen " kStatisticItemByGroupAndCase "Gruppe.

Wenn Sie genau hinsehen, werden Sie feststellen, dass dies nicht komplizierter ist als das, was Sie bereits tun. :-)


EDIT: Ein letzter Hinweis. Ich persönlich finde das viel ausdrucksvoller als die oben genannte Ausdrücke, weil es Knoten Gleichheit betont viel mehr als die „count(.|something) = 1“ -Ansatz:

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

Das Ergebnis ist das gleiche.