I'm trying to use Muenchian grouping to display company policy documents in a hierarchical way. The policy documents are all added to SharePoint and tagged with a Language, a category and a document type. I'm then using the XML that this creates.
I need to take the data from 2 merged lists. The way SharePoint works, my XML looks like this (with a Rows element for each SharePoint list): I've had to simplify this to remove the hundreds of attributes that SP adds as it went over the stackoverflowsize limit, but the structure is accurate.
<dsQueryResponse>
<Rows>
<Row Title="Testitem" Category="Category 1" Language="English" DocumentType="Content" />
</Rows>
<Rows>
<Row Title="Doc1" Category="Category 1" Language="English" DocumentType="Policy" />
<Row Title="Policy2" Category="Category 2" Language="English" DocumentType="Policy" />
<Row Title="Policy3" Category="Category 1" Language="Nederlands (Dutch)" DocumentType="Form" />
</Rows>
</dsQueryResponse>
Current xsl looks like this:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:SharePoint="Microsoft.SharePoint.WebControls"
xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer"
xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource"
xmlns:asp="http://schemas.microsoft.com/ASPNET/20"
xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
xmlns:ddwrt2="urn:frontpage:internal"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:x="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xsl msxsl ddwrt"
ddwrt:oob="true"
>
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:key name="byLANGUAGE" match="/dsQueryResponse/Rows/Row" use="@Language" />
<xsl:key name="byCATEGORY" match="/dsQueryResponse/Rows/Row" use="concat(@Language, '+', @Category)" />
<xsl:template match="/">
<xsl:apply-templates select="/dsQueryResponse/Rows/Row[count(. | key('byLANGUAGE', @Language)[1]) = 1]/@Language">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="@Language">
<br /><b>Below you can see all policies in <xsl:value-of select="." /></b><br /><br />
<xsl:variable name="thisLanguage" select="key('byLANGUAGE', .)" />
<xsl:apply-templates select="$thisLanguage[count(. | key('byCATEGORY', concat(@Language, '+', @Category))[1])= 1]/@Category">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="@Category">
<br />Category: <xsl:value-of select="." />
<xsl:apply-templates select="key('byCATEGORY', concat(../@Language, '+', .))" />
</xsl:template>
<xsl:template match="/dsQueryResponse/Rows/Row">
<br />Title: <xsl:value-of select="@Title" />
</xsl:template>
</xsl:stylesheet>
and current result looks like this (a mess):
Below you can see all policies in English Category: Category 1 Title: Testitem Category: Category 2 Title: Policy2 Below you can see all policies in English Category: Category 1 Title: Testitem Category: Category 2 Title: Policy2 Below you can see all policies in Nederlands (Dutch) Category: Category 1 Title: Policy3 **My desired output is:** Below you can see all policies in English Category: Category 1 Title: Testitem Title: Doc1 Category: Category 2 Title: Policy2 Below you can see all policies in Nederlands (Dutch) Category: Category 1 Title: Policy3
So I seem to be getting lots of duplication, presumably because something is getting called twice, once for each of the Rows elements? I'm a novice with XSL so any help would be appreciated.
========== UPDATE ==========
The code below now works for me in SharePoint (the bulky looking Choose statements aren't technically necessary but I needed them to get rid of the non-English characters for the JQuery that I've put on top of this):
Full XSLT:
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" ddwrt:oob="true">
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="byLANGUAGE" match="/dsQueryResponse/Rows/Row" use="@Language" />
<xsl:key name="byCATEGORY" match="/dsQueryResponse/Rows/Row" use="concat(@Language, '+', @Category)" />
<xsl:template match="/">
<div id="tabs" style="display:none;">
<!--Create tabs-->
<ul>
<xsl:apply-templates select="/dsQueryResponse/Rows/Row[count(. | key('byLANGUAGE', @Language)[2]) = 1]/@Language">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</ul>
<!--Create content-->
<xsl:apply-templates select="/dsQueryResponse/Rows/Row[count(. | key('byLANGUAGE', @Language)[2]) = 1]/@Language" mode="pass2">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</div>
</xsl:template>
<!--Do a first pass to create the tabs -->
<xsl:template match="@Language">
<li>
<xsl:choose>
<xsl:when test=". = 'English'"><xsl:text disable-output-escaping="yes"><a href="#English"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Bahasa'"><xsl:text disable-output-escaping="yes"><a href="#Bahasa"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = '简体中文 (Chinese)'"><xsl:text disable-output-escaping="yes"><a href="#Chinese"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Nederlands (Dutch)'"><xsl:text disable-output-escaping="yes"><a href="#Dutch"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Français (French)'"><xsl:text disable-output-escaping="yes"><a href="#French"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Deutsch (German)'"><xsl:text disable-output-escaping="yes"><a href="#German"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Italiano (Italian)'"><xsl:text disable-output-escaping="yes"><a href="#Italian"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = '日本語 (Japanese)'"><xsl:text disable-output-escaping="yes"><a href="#Japanese"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = '한국의 (Korean)'"><xsl:text disable-output-escaping="yes"><a href="#Korean"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Polski (Polish)'"><xsl:text disable-output-escaping="yes"><a href="#Polish"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Português (Portuguese)'"><xsl:text disable-output-escaping="yes"><a href="#Portuguese"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'PyccĸИЙ (Russian)'"><xsl:text disable-output-escaping="yes"><a href="#Russian"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
<xsl:when test=". = 'Castellano (Spanish)'"><xsl:text disable-output-escaping="yes"><a href="#Spanish"></xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes"></a></xsl:text></xsl:when>
</xsl:choose>
</li>
</xsl:template>
<!--and a second pass to do everything else-->
<xsl:template match="@Language" mode="pass2">
<xsl:choose>
<xsl:when test=". = 'English'"><xsl:text disable-output-escaping="yes"><div id="English"></xsl:text></xsl:when>
<xsl:when test=". = 'Bahasa'"><xsl:text disable-output-escaping="yes"><div id="Bahasa"></xsl:text></xsl:when>
<xsl:when test=". = '简体中文 (Chinese)'"><xsl:text disable-output-escaping="yes"><div id="Chinese"></xsl:text></xsl:when>
<xsl:when test=". = 'Nederlands (Dutch)'"><xsl:text disable-output-escaping="yes"><div id="Dutch"></xsl:text></xsl:when>
<xsl:when test=". = 'Français (French)'"><xsl:text disable-output-escaping="yes"><div id="French"></xsl:text></xsl:when>
<xsl:when test=". = 'Deutsch (German)'"><xsl:text disable-output-escaping="yes"><div id="German"></xsl:text></xsl:when>
<xsl:when test=". = 'Italiano (Italian)'"><xsl:text disable-output-escaping="yes"><div id="Italian"></xsl:text></xsl:when>
<xsl:when test=". = '日本語 (Japanese)'"><xsl:text disable-output-escaping="yes"><div id="Japanese"></xsl:text></xsl:when>
<xsl:when test=". = '한국의 (Korean)'"><xsl:text disable-output-escaping="yes"><div id="Korean"></xsl:text></xsl:when>
<xsl:when test=". = 'Polski (Polish)'"><xsl:text disable-output-escaping="yes"><div id="Polish"></xsl:text></xsl:when>
<xsl:when test=". = 'Português (Portuguese)'"><xsl:text disable-output-escaping="yes"><div id="Portuguese"></xsl:text></xsl:when>
<xsl:when test=". = 'PyccĸИЙ (Russian)'"><xsl:text disable-output-escaping="yes"><div id="Russian"></xsl:text></xsl:when>
<xsl:when test=". = 'Castellano (Spanish)'"><xsl:text disable-output-escaping="yes"><div id="Spanish"></xsl:text></xsl:when>
</xsl:choose>
<b>Below you can see all policies in <xsl:value-of select="." /></b><br /><br/>
<div class="accordion">
<xsl:variable name="thisLanguage" select="key('byLANGUAGE', .)" />
<xsl:apply-templates select="$thisLanguage[count(. | key('byCATEGORY', concat(@Language, '+', @Category))[2])= 1]/@Category">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</div>
<xsl:text disable-output-escaping="yes"></div></xsl:text>
</xsl:template>
<xsl:template match="@Category">
<h3>
<xsl:value-of select="." />
</h3>
<div class="accordionContent">
<xsl:apply-templates select="key('byCATEGORY', concat(../@Language, '+', .))"/>
</div>
</xsl:template>
<xsl:template match="/dsQueryResponse/Rows/Row">
<div class="policy-item">
<div class="policy-item-title">
<xsl:value-of select="@Title" />
</div>
<xsl:if test="@ItemHtml != ''">
<div class="policy-item-content">
<xsl:value-of select="@ItemHtml" disable-output-escaping="yes" />
</div>
</xsl:if>
</div>
</xsl:template>
</xsl:stylesheet>