sharepointxsltdataviewwebpart

XSLT Count Distinct in a Group (Data View Web Part)


I am working on a data view web part in SP 2010 to rullup some information from sub sites. These sites contain project task lists that have tasks assigned to users. The customer wants to see a rollup that will list projects by user based on whether or not they have tasks assigned. Since a project can have multiple tasks, a project could show up under multiple users in the rollup, depending on which tasks are assigned to which users.

Long story short, I need a way to select the count of distinct projects for each user.

The xml structure is like this:

<Rows>
  <Row Project="Project 1" TaskID="1" AssignedTo="Worker A" />
  <Row Project="Project 1" TaskID="2" AssignedTo="Worker B" />
</Rows>

From this, I would expect the following for project counts:
Worker A: 1
Worker B: 1

I am trying the following formula:

count($nodeset[not(@Project=preceding-sibling::Row/@Project) and @AssignedTo = current()/@AssignedTo])

This returns a count of 1 project for Worker A, but it returns 0 for Worker B, because Project 1 has already been counted for Worker A.

I don't know much about xslt, but from what I understand, using current() is not the most resource-friendly method. I've tried to do the muenchian grouping but I haven't been able to get it to work. Willing to try again though. Any advice would be helpful, as, again, I stink with xslt.


Solution

  • This transformation:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:key name="kWorker" match="@AssignedTo" use="."/>
     <xsl:key name="kProjByWorker" match="@Project" use="../@AssignedTo"/>
     <xsl:key name="kProjWorker" match="@Project" use="concat(.,'+',../@AssignedTo)"/>
    
     <xsl:template match="/*">
      <xsl:apply-templates select=
      "//@AssignedTo
         [generate-id()
         =
          generate-id(key('kWorker',.)[1])
          ]"/>
     </xsl:template>
    
     <xsl:template match="@AssignedTo">
      <xsl:value-of select="concat('&#xA;',.,': ')"/>
    
      <xsl:value-of select=
       "count(
         key('kProjByWorker', .)
           [generate-id()
           =
            generate-id(key('kProjWorker', concat(.,'+',current()))[1])]
         )"/>
     </xsl:template>
    </xsl:stylesheet>
    

    when applied on the following XML document (a more challenging version of the provided one):

    <Rows>
      <Row Project="Project 1" TaskID="1" AssignedTo="Worker A" />
      <Row Project="Project 1" TaskID="2" AssignedTo="Worker B" />
      <Row Project="Project 1" TaskID="2" AssignedTo="Worker A" />
      <Row Project="Project 2" TaskID="1" AssignedTo="Worker A" />
    </Rows>
    

    produces the wanted, correct result:

    Worker A: 2
    Worker B: 1
    

    Explanation:

    Use of the Muenchian grouping method twice: to find all different workers, and then to find the distinct projects assigned to this worker.