xml - Treating sibling nodes as one for XSLT Muenchian grouping -
i'm trying use muenchian grouping display company policy documents in hierarchical way. policy documents added sharepoint , tagged language, category , document type. i'm using xml creates.
i need take data 2 merged lists. way sharepoint works, my xml looks (with rows element each sharepoint list): i've had simplify remove hundreds of attributes sp adds went on stackoverflowsize limit, structure 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 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 can see 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 (a mess):
below can see policies in english category: category 1 title: testitem category: category 2 title: policy2 below can see policies in english category: category 1 title: testitem category: category 2 title: policy2 below can see policies in nederlands (dutch) category: category 1 title: policy3 **my desired output is:** below can see policies in english category: category 1 title: testitem title: doc1 category: category 2 title: policy2 below can see policies in nederlands (dutch) category: category 1 title: policy3
so seem getting lots of duplication, presumably because getting called twice, once each of rows elements? i'm novice xsl appreciated.
========== update ==========
the code below works me in sharepoint (the bulky looking choose statements aren't technically necessary needed them rid of non-english characters jquery 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 first pass create 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 second pass 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 can see 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>
here do:
<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="msxsl ddwrt sharepoint __designer agg asp d ddwrt2 x" ddwrt:oob="true" > <xsl:output method="html" indent="yes" omit-xml-declaration="yes" /> <xsl:key name="krowbylanguage" match="row" use="@language" /> <xsl:key name="krowbycategory" match="row" use="concat(@language, '+', @category)" /> <xsl:template match="/"> <html> <body> <xsl:apply-templates select="dsqueryresponse/rows" /> </body> </html> </xsl:template> <xsl:template match="rows"> <xsl:apply-templates mode="language" select="row[ count(. | key('krowbylanguage', @language)[1]) = 1 ]"> <xsl:sort select="@language" order="ascending" /> </xsl:apply-templates> </xsl:template> <xsl:template match="row" mode="language"> <xsl:variable name="mycategory" select="concat(@language, '+', @category)" /> <div class="language"> <div> <xsl:text>below can see policies in </xsl:text> <xsl:value-of select="@language" /> </div> <div> <xsl:apply-templates mode="category" select="key('krowbylanguage', @language)[ count(. | key('krowbycategory', $mycategory)[1]) = 1 ]"> <xsl:sort select="@category" order="ascending" /> </xsl:apply-templates> </div> </div> </xsl:template> <xsl:template match="row" mode="category"> <xsl:variable name="mycategory" select="concat(@language, '+', @category)" /> <div class="catecory"> <div> <xsl:text>category: </xsl:text> <xsl:value-of select="@category" /> </div> <div> <xsl:apply-templates mode="title" select="key('krowbycategory', $mycategory)" /> </div> </div> </xsl:template> <xsl:template match="row" mode="title"> <div> <xsl:text>title: </xsl:text> <xsl:value-of select="@title" /> </div> </xsl:template> </xsl:stylesheet>
output (i recommend using css formatting output, instead of using <br>
):
<html> <body> <div class="language"> <div>below can see policies in english</div> <div> <div class="catecory"> <div>category: category 1</div> <div> <div>title: testitem</div> <div>title: doc1</div> </div> </div> </div> </div> <div class="language"> <div>below can see policies in nederlands (dutch)</div> <div> <div class="catecory"> <div>category: category 1</div> <div> <div>title: policy3</div> </div> </div> </div> </div> </body> </html>
the primary change move of subgroup key (language + category) variable $mycategory
, enables selecting right nodes in double grouping.
your original expression:
$thislanguage[count(. | key('bycategory', concat(@language, '+', @category))[1])= 1]
refers wrong context inside predicate (it refers $thislanguage
, not have @language or @category). moving concat(...)
out of expression generates correct results.
the secondary change adding structure output can targeted more via css.
also note output method , use of different template modes.
general hint: have many namespace declarations in stylesheet. remove don't actively use in stylesheet.
Comments
Post a Comment