Generating tag cloud using the Content Query Web Part
Content Query Web Part, Customization, SharePoint, WCM, XSLTBy now you should know how powerful the Content Query Web Part (CQWP) provided with Microsoft Office SharePoint Server (MOSS) 2007 is. If you’ve been following this blog for a while it should be really difficult to surprise you with cool new things you could do with nothing more than the standard CQWP. And yet, I think I make a good chance here: did you know that you can use the standard Content Query Web Part to create a tag cloud?
Tag Clouds and SharePoint
Tag Clouds provide an alternative way of navigating through your site. Using a tag cloud you can help your visitors discover the content on your site. By using different font sizes (or any other kind of styling) you can mark the most important (either if it’s the most often visited, the category contains most articles, etc.) so they can easily get to that information.
You can find tag clouds on many sites hosted on many different Content Management Systems (CMS) on the Internet. It’s surprising though, that SharePoint doesn’t contain a standard Tag Cloud Web Part, does it? Just recently I have done some research and found out that you could actually create a Tag Cloud using nothing more than the standard Content Query Web Part provided with MOSS 2007.
Requirements
We want to change this:
into this:
The only limitation we have is that we cannot use any custom code at all (that means no subclassed CQWP and no custom XPath functions as well). All we are allowed to do is to use the standard Content Query Web Part and change the XSLT.
As the data source we will use some press releases (also available with the standard MOSS 2007 Publishing Site). Each press release belongs to exactly one category (custom choice field):
What we want to do is to create a Tag Cloud of all categories in which we will highlight the categories with the most press releases.
Let’s get to work
To simplify the whole process let’s break it into some steps.
First of all we need to get all the different categories assigned to press releases. Because we’re using a custom choice field here, we could simply hard code them in the XSLT. That would however limit our Tag Cloud: in the Category choice field we have allowed fill-in choices so that the content editors can create new categories if needed. So instead of changing the XSLT every time a content editor adds a new category, let’s retrieve them dynamically.
The next step is to perform a count: how many times each category has been used. In other words: how many different press releases are there in every category. Based on that number we will determine the relative importance of every category.
Then we need to determine which category contains the most posts. This will be our measure point to determine the relative importance of every category.
To make the process a bit more understandable let’s start off with a simple XML file, make the XSLT work and then move it to the Content Query Web Part. I’m going to base the case on the following XML file:
<?xml version="1.0" encoding="utf-8"?> <Rows> <Row Category="SharePoint"/> <Row Category="Content Query Web Part"/> <Row Category="Structured and Repeatable Deployment"/> <Row Category="WCM"/> <Row Category="SharePoint"/> <Row Category="SharePoint"/> <Row Category="Structured and Repeatable Deployment"/> <Row Category="SharePoint"/> <Row Category="SharePoint"/> <Row Category="WCM"/> <Row Category="WCM"/> <Row Category="Content Query Web Part"/> <Row Category="Content Query Web Part"/> <Row Category="Content Query Web Part"/> <Row Category=".NET"/> </Rows>
Later on we will modify the Tag Cloud XSLT to work in the CQWP.
Getting different categories
We can retrieve all the different categories using one single XPath function (→ means a forced line break. In the real code it would be in one line):
<xsl:variable name="TagsArray"→ select="Row[not(@Category=preceding-sibling::→ Row/@Category)]/@Category"/>
Although it seems pretty complex it works very simple: for each node the value of the Category attribute is being compared the value of the Category attribute of the previous sibling node. Because the function is included in a not clause we will get all the distinct categories. Because it’s just the beginning and we want to do something with the categories, let’s store them in a variable.
How many press releases are there in each category?
If you were asked do perform a similar count in .NET code, you would most likely create a Dictionary of string and int, where the key would represent a category and the value the number of press releases. Using a for each loop you would step through all the categories and store the counts in a new variable. The bad news is that you cannot do such thing in XSLT. Once you set a value of a variable, you cannot change it. So how to get this done?
One solution I thought of was creating an XML document with all the categories and the count for each category:
<tags> <tag Name="SharePoint" Count="3"/> <tag Name="Content Query Web Part" Count="1"/> // ... </tags>
I have created the following template:
<xsl:template name="Imtech.CountPerTag">
<xsl:param name="Tags"/>
<tags>
<xsl:for-each select="$Tags">
<xsl:variable name="Name" select="self::node()"/>
<tag>
<xsl:attribute name="Name">
<xsl:value-of select="$Name"/>
</xsl:attribute>
<xsl:attribute name="Count">
<xsl:value-of
select="count(/Rows/Row[@Category=$Name])"/>
</xsl:attribute>
</tag>
</xsl:for-each>
</tags>
</xsl:template>
and then called it passing the TagsArray variable as Tags parameter:
<xsl:variable name="TagsRawXml">
<xsl:call-template name="Imtech.CountPerTag">
<xsl:with-param name="Tags" select="$TagsArray"/>
</xsl:call-template>
</xsl:variable>
Once again let’s store the results in a variable. We’re not there yet and we will do some more processing before we will get a tag cloud.
If you look carefully at the last snippet you see, that I called the variable TagsRawXml. So why the Raw part and not just TagsXml? The reason for this is pretty simple. The Imtech.CounterPerTag produces string output. Before we can process it as an XML document, we have to convert it to a node set using the msxsl:node-set() function:
<xsl:variable name="Tags" select="msxsl:node-set($TagsRawXml)"/>
Now we know for each category how many press releases it has, we can move on and cover our next challenge.
Determining the maximum value
Tag Cloud is all about relativity. One of the items determines the upper boundary and then all the other items are being formatted depending on their relative importance comparing to the upper boundary.
XSLT has an XPath max function. The downside is that it returns the maximum value from a list of arguments, not the maximum value of an attribute from a node set. In other words, we have to create a custom solution to get things done:
<xsl:variable name="MaxValue"→ select="$Tags/tags/tag[not(@Count <= → preceding-sibling::tag/@Count) and → not(@Count <= following-sibling::tag/@Count)]/@Count"/>
Once again it seems pretty complex but it isn’t: the value of every Count attribute is being compared with the value of the previous and the next Count attribute and is being returned only if it’s bigger than the two other Count attributes.
So far we have done quite a few things. Let’s wrap it up and check out the results:
<?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="html" indent="yes"/>
<xsl:template match="/Rows">
<xsl:call-template name="Imtech.TagCloud"/>
</xsl:template>
<xsl:template name="Imtech.TagCloud">
<xsl:variable name="TagsArray"
select="Row[not(@Category=preceding-sibling::→
Row/@Category)]/@Category"/>
<xsl:variable name="TagsRawXml">
<xsl:call-template name="Imtech.CountPerTag">
<xsl:with-param name="Tags" select="$TagsArray"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="Tags"
select="msxsl:node-set($TagsRawXml)"/>
<xsl:variable name="MaxValue"
select="$Tags/tags/tag[not(@Count <= →
preceding-sibling::tag/@Count) and →
not(@Count <= following-sibling::tag/@Count)]/@Count"/>
<xsl:for-each select="$Tags/tags/tag">
<a>
<xsl:attribute name="href">
<xsl:value-of
select="concat(→
'/Pages/SearchResults.aspx?k=', @Name)"/>
</xsl:attribute>
<xsl:value-of select="@Name"/>
</a>
<xsl:text disable-output-escaping="yes">
<![CDATA[ ]]></xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="Imtech.CountPerTag">
<xsl:param name="Tags"/>
<tags>
<xsl:for-each select="$Tags">
<xsl:variable name="Name" select="self::node()"/>
<tag>
<xsl:attribute name="Name">
<xsl:value-of select="$Name"/>
</xsl:attribute>
<xsl:attribute name="Count">
<xsl:value-of
select="count(/Rows/Row[@Category=$Name])"/>
</xsl:attribute>
</tag>
</xsl:for-each>
</tags>
</xsl:template>
</xsl:stylesheet>
We are not there just yet: so far we have managed to get the list of all the distinct categories attached to the press releases. But as we wanted to create a Tag Cloud, we need to do something with formatting. At some point we retrieved the upper boundary for our Tag Cloud – the category with the most press releases. Let’s use it to determine the font size for each category depending on how many press releases it has.
First let’s create a template to get us the right formatting:
<xsl:template name="Imtech.GetRelativeFontSize">
<xsl:param name="CurrentValue"/>
<xsl:param name="MaxValue"/>
<xsl:param name="relativeValue"
select="($CurrentValue div $MaxValue)*100"/>
<xsl:choose>
<xsl:when test="$relativeValue < 14">xx-small</xsl:when>
<xsl:when test="$relativeValue < 28">x-small</xsl:when>
<xsl:when test="$relativeValue < 42">small</xsl:when>
<xsl:when test="$relativeValue < 56">medium</xsl:when>
<xsl:when test="$relativeValue < 70">large</xsl:when>
<xsl:when test="$relativeValue < 84">x-large</xsl:when>
<xsl:otherwise>xx-large</xsl:otherwise>
</xsl:choose>
</xsl:template>
The relevance of a category comparing to the upper boundary is being calculated as a percentage. To keep it simple I have used the seven predefined font-sizes as formatting but nothing stops you to use things like colors, different font weights, styling, etc.
Let’s extend our Tag Cloud template:
<?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="html" indent="yes"/>
<xsl:template match="/Rows">
<xsl:call-template name="Imtech.TagCloud"/>
</xsl:template>
<xsl:template name="Imtech.TagCloud">
<xsl:variable name="TagsArray"
select="Row[not(@Category=preceding-sibling::→
Row/@Category)]/@Category"/>
<xsl:variable name="TagsRawXml">
<xsl:call-template name="Imtech.CountPerTag">
<xsl:with-param name="Tags" select="$TagsArray"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="Tags"
select="msxsl:node-set($TagsRawXml)"/>
<xsl:variable name="MaxValue"
select="$Tags/tags/tag[not(@Count <= →
preceding-sibling::tag/@Count) and →
not(@Count <= following-sibling::→
tag/@Count)]/@Count"/>
<xsl:for-each select="$Tags/tags/tag">
<xsl:variable name="fontSize">
<xsl:call-template name="Imtech.GetRelativeFontSize">
<xsl:with-param name="CurrentValue" select="@Count"/>
<xsl:with-param name="MaxValue" select="$MaxValue"/>
</xsl:call-template>
</xsl:variable>
<a>
<xsl:attribute name="style">
<xsl:value-of
select="concat('font-size: ', $fontSize)"/>
</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of
select="concat('/Pages/SearchResults.aspx?k=', →
@Name)"/>
</xsl:attribute>
<xsl:value-of select="@Name"/>
</a>
<xsl:text disable-output-escaping="yes">
<![CDATA[ ]]></xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="Imtech.CountPerTag">
<xsl:param name="Tags"/>
<tags>
<xsl:for-each select="$Tags">
<xsl:variable name="Name" select="self::node()"/>
<tag>
<xsl:attribute name="Name">
<xsl:value-of select="$Name"/>
</xsl:attribute>
<xsl:attribute name="Count">
<xsl:value-of
select="count(/Rows/Row[@Category=$Name])"/>
</xsl:attribute>
</tag>
</xsl:for-each>
</tags>
</xsl:template>
<xsl:template name="Imtech.GetRelativeFontSize">
<xsl:param name="CurrentValue"/>
<xsl:param name="MaxValue"/>
<xsl:param name="relativeValue"
select="($CurrentValue div $MaxValue)*100"/>
<xsl:choose>
<xsl:when test="$relativeValue < 14">xx-small</xsl:when>
<xsl:when test="$relativeValue < 28">x-small</xsl:when>
<xsl:when test="$relativeValue < 42">small</xsl:when>
<xsl:when test="$relativeValue < 56">medium</xsl:when>
<xsl:when test="$relativeValue < 70">large</xsl:when>
<xsl:when test="$relativeValue < 84">x-large</xsl:when>
<xsl:otherwise>xx-large</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
and check out the results:
Looks better doesn’t it? Now we have it all working in Visual Studio, let’s move it to the Content Query Web Part.
Content Query Web Part and XSLT
The Content Query Web Part uses three different XSL files to do the data rendering:
- ItemStyle.xsl which contains different styles for rendering items
- Header.xsl which contains different styles for rendering groups
- ContentQueryMain.xsl which is responsible for rendering the body of the web part, applying the proper headers and items formatting etc.
The basic idea is that the ContentQueryMain is being applied once to the query result and the item styles from ItemStyle.xsl are being applied to every single item (Row in the query results XML).
Looking at the template you can see that we’re starting from the top and perform the whole process of selection ourselves. The first thing you might think of would to include the whole template in the ContentQueryMain.xsl and replace the default rendering with our Tag Cloud template. While you could do that, it would mean that the Content Query Web Part with that XSL attached to it wouldn’t be capable of rendering anything else than a Tag Cloud. There is a more flexible way to get it working.
First of all we still need to include the whole template in the ContentQueryMain.xsl. Additionally we will define an empty Imtech.TagCloud template in ItemStyle.xsl so that we can select the formatting using the Content Query Web Part presentation settings:
The Content Query Web Part attaches the information about the selected item style to each query result row as an extra attribute (Style):
Knowing that we can extend the ContentQueryMain with conditional rendering: if the chosen Item style is Imtech.TagCloud the CQWP should use our template and otherwise it should stick to the default rendering process.
If you save the changes done to the ContentQueryMain.xsl and reload the page you will get an error:
Although the Content Query Web Part supports functions from the msxsl namespace, the ContentQueryMain.xsl doesn’t reference it. You can fix this error by including it in the header of the ContentQueryMain.xsl file:
Let’s have a look at the results again:
Summary
You can do really amazing things with the Content Query Web Part. Because it uses XSLT it allows you to customize the data presentation in many different ways. Even if you’re not allowed to subclass it and extend it with custom XPath functions, you can do some great customizations with the standard functionality.
Complete template
In ItemStyle.xsl
<xsl:template name="Imtech.TagCloud" match="Row[@Style='Imtech.TagCloud']" mode="itemstyle"/>
In ContentQueryMain.xsl
File Header:
<xsl:stylesheet
version="1.0"
exclude-result-prefixes="x xsl cmswrt cbq msxsl"
xmlns:x="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cmswrt="http://schemas.microsoft.com/WebPart/v3/Publishing/runtime"
xmlns:cbq="urn:schemas-microsoft-com:ContentByQueryWebPart"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
OuterTemplate template:
...
<xsl:choose>
<xsl:when test="$IsEmpty">
<xsl:call-template name="OuterTemplate.Empty" >
<xsl:with-param name="EditMode" select="$cbq_iseditmode" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when
test="/dsQueryResponse/Rows/Row[1]/→
@Style='Imtech.TagCloud'">
<td>
<xsl:call-template name="Imtech.TagCloud" />
</td>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="OuterTemplate.Body">
<xsl:with-param name="Rows" select="$Rows" />
<xsl:with-param name="FirstRow" select="1" />
<xsl:with-param name="LastRow" select="$RowCount" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
...
At the end of the file:
<xsl:template name="Imtech.TagCloud">
<xsl:variable name="TagsArray"
select="/dsQueryResponse/Rows/Row[→
not(@Category=preceding-sibling::Row/@Category)]/@Category"/>
<xsl:variable name="TagsRawXml">
<xsl:call-template name="Imtech.CountPerTag">
<xsl:with-param name="Tags" select="$TagsArray"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="Tags" select="msxsl:node-set($TagsRawXml)"/>
<xsl:variable name="MaxValue"
select="$Tags/tags/tag[not(@Count <= →
preceding-sibling::tag/@Count) and →
not(@Count <= following-sibling::tag/@Count)]/@Count"/>
<xsl:for-each select="$Tags/tags/tag">
<xsl:variable name="fontSize">
<xsl:call-template name="Imtech.GetRelativeFontSize">
<xsl:with-param name="CurrentValue" select="@Count"/>
<xsl:with-param name="MaxValue" select="$MaxValue"/>
</xsl:call-template>
</xsl:variable>
<a>
<xsl:attribute name="style">
<xsl:value-of select="concat('font-size: ', $fontSize)"/>
</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of
select="concat('/Pages/SearchResults.aspx?k=', @Name)"/>
</xsl:attribute>
<xsl:value-of select="@Name"/>
</a>
<xsl:text disable-output-escaping="yes">
<![CDATA[ ]]></xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="Imtech.CountPerTag">
<xsl:param name="Tags"/>
<tags>
<xsl:for-each select="$Tags">
<xsl:variable name="Name" select="self::node()"/>
<tag>
<xsl:attribute name="Name">
<xsl:value-of select="$Name"/>
</xsl:attribute>
<xsl:attribute name="Count">
<xsl:value-of
select="count(/dsQueryResponse/Rows/Row[→
@Category=$Name])"/>
</xsl:attribute>
</tag>
</xsl:for-each>
</tags>
</xsl:template>
<xsl:template name="Imtech.GetRelativeFontSize">
<xsl:param name="CurrentValue"/>
<xsl:param name="MaxValue"/>
<xsl:param name="relativeValue"
select="($CurrentValue div $MaxValue)*100"/>
<xsl:choose>
<xsl:when test="$relativeValue < 14">xx-small</xsl:when>
<xsl:when test="$relativeValue < 28">x-small</xsl:when>
<xsl:when test="$relativeValue < 42">small</xsl:when>
<xsl:when test="$relativeValue < 56">medium</xsl:when>
<xsl:when test="$relativeValue < 70">large</xsl:when>
<xsl:when test="$relativeValue < 84">x-large</xsl:when>
<xsl:otherwise>xx-large</xsl:otherwise>
</xsl:choose>
</xsl:template>

















April 24th, 2009 at 3:48 pm
Can the same thing be achieved with only the XSL in the CQWP?
April 24th, 2009 at 4:02 pm
@Matt: it is XSL from the CQWP. Or do you mean something else?
April 24th, 2009 at 4:06 pm
Sorry, I was not very clear!
I do not have access to the .xsl files, only to xsl in the webpart, is there a way of getting this working without editing these files?
My use case is: as a user of MOSS (not admin etc) I want to add this to the blog that hangs off my MySite, this is the scope of my permissions!
April 24th, 2009 at 4:27 pm
Related post on using Tag Clouds with the Data Form Web Part: http://www.iwkid.com/blog/Lists/Posts/Post.aspx?ID=39
April 24th, 2009 at 5:34 pm
Wow – my first visit to your site (thanks to your Twitter) and I'm impressed with the quality and amount of interesting MOSS / WSS code here.
I'll be giving this a spin before going with a commercial tagging engine for our MOSS sites.
April 24th, 2009 at 11:28 pm
@Matt: CQWP doesn't contain any XSLT in it. All it does is referencing existing XSL files. If you have no permitions to the standard XSL files, you can create your own, upload them to a Document Library and make the CQWP point to your custom XSLT instead of the standard ones. As long as you can upload files and edit Web Parts, you should be able to get it working.
April 24th, 2009 at 11:31 pm
@Robin Majumdar: thanks. Glad to hear you find the content useful
April 29th, 2009 at 1:06 pm
Hello Guys,
My issue is: I have a Portal and want to create a Tag cloud there which contains tags refering to different lists situated on different sites/pages.. Can it really works because up to now I see solutions where the tag cloud works only for one certain Site.
thank you!
Stanislava
April 29th, 2009 at 4:40 pm
@Stanislava Goranova: What you need is a mechanism to distinct which tags belong to which list. Depending on that mechanism you could redirect different tags to different pages.
April 29th, 2009 at 5:07 pm
Hi,
Other ideas.. I do not need to distinct which tag belongs to which list but I need to render all tags from all lists from all pages to the webpart (tag cloud) on the Portal.
You are right..in general.. but the tag could should refer to lists where certain words are tagged, so when clicking on certain word from the cloud I go to a separate page where all the lists incl. that particular tag are listed. So, I need smth else indeed..
thank you!stanislava
April 29th, 2009 at 11:40 pm
@Stanislava Goranova: using the standard Content Query Web Part you can query across the whole Site Collection, so it should be possible for you to retrieve the results you mentioned. As for the tag target link: you can set it in XSLT by yourself.
May 7th, 2009 at 4:10 am
Your blog post has been replicated by someone else – http://martijnmolegraaf.blogspot.com/2009/05/generating-tag-cloud-using-content.html. Seems like you were the first one. Just thought you'd want to know.
May 7th, 2009 at 2:29 pm
@Lisa: Thanks for letting me know. The author has been contacted and the issue has been solved.
May 18th, 2009 at 3:17 pm
Hi Waldek
Great work!
The CQWP never ceases to amaze me when people push its boundaries.
You must dream XSLT
The only thing I think missing from this article for the final solution is that you will have to export the CQWP and modify the CommonViewFields property so the CQWP can see the Category data
<property name=\"CommonViewFields\" type=\"string\">Category,Choice;</property>
May 18th, 2009 at 5:22 pm
@Clayton: Good one: I forgot to include it in the process. Thanks for pointing this out.
June 15th, 2009 at 10:23 pm
Waldek – I was curious about how to customize this solution to work with category fields that are multi-choice (checkboxes). Since you can't create views based on this type of field, I thought it'd be a great idea to use a tag cloud to help visualize the relative number of items in each category. I'm stuck in trying to modify the XSLT to parse out the category field which would look something like Book; Website. Have you tried something like that and would be able to share?
June 15th, 2009 at 10:32 pm
@Lisa: It seems indeed like a next logical step from this article. Although I've been thinking about it, I haven't tried it yet. Perhaps I will give it a shot in the future.
June 16th, 2009 at 6:18 am
Great work. But i just confuse and wondering how able to split multiple tags name that using seperator as ";" on the tag column in XSL, for example, an item being tag as SharePoint; .Net; Web Part. The tags cloud should treat each of entity\ies as single tag value SharePoint .Net Web Part.
June 16th, 2009 at 6:30 am
@Zen: As I have mentioned: I haven't come with a solution supporting multiple tags yet. I'm quite sure though that there is a way to get it done.
June 19th, 2009 at 6:45 am
Hi there,
I need to call a function from within my itemstyle.xsl document.
My javascript is like this (simple, and is contained in content editor web part on the same page):
var noSubs = 0;
incrementSubs();
getSubs();
function incrementSubs()
{
noSubs++;
}
function getSubs()
{
return noSubs;
}
In my itemstyle.xsl, I have a test between to variables. Upon the result, I would like to call incrementSubs();.
Then, at a later stage in the xslt, I would like to use getSubs(); in a mathematical calculation for another test.
How can this be done?
Cheers!
June 19th, 2009 at 7:09 am
@oneilaus: As far as I know you should be able to include JavaScript in an XSL file. Simply add it in a CDATA block (< ![CDATA[ JavaScript goes here ]]>) so that it won't get parsed by the XML engine and you should see your script in the rendered HTML output.
June 26th, 2009 at 4:15 pm
Waldek – I was trying to solve the problem of how to process categories that are delimited. (See my comment above from June 15th) I created this MSDN forum post (http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx/thread/b24edf67-3488-432b-9744-68a1cba0e51c) and the response to do recursion to split the category values into individual rows seems logical but I can\'t get it into a node-set. I was hoping you might have a suggestion?
June 29th, 2009 at 4:55 pm
@Lisa: Have you had a look at the EXSLT functions (http://www.exslt.org/exsl/functions/node-set/index.html)? .NET is available for download so it should give you some idea of how to create your own function which would return a node-set.
July 8th, 2009 at 1:16 am
Waldek, in your answer on April 24, you mentioned to Matt to …\"make the CQWP point to your custom XSLT instead of the standard ones\". I can upload files and edit the CQWP. How do you make the CQWP point to the custom files?
July 8th, 2009 at 7:20 am
@David: if you're using the Extended Content Query Web Part from Podcasting Kit for SharePoint there is a new property in the ToolPartPane to provide the URL. If you're using the standard CQWP however, you need to export your Web Part and provide the URL to your custom XSLT using the 'ItemXslLink' property.
July 30th, 2009 at 4:16 pm
Hi Waldek,
I m lucky to have landed to this site. This is exactly I needed to include additional columns to display and style them.
I tried adding to the property as
/Style Library/XSL Style Sheets/MyCustom.xsl
When uploading it, it says the webpart cannot be loaded.
Any help is very much appreciated. Do u have a post wher e end-to-end there is sample implementation of adding new fields to CQWP and styling it using custom XSL.
Cheers,
Akshay
August 2nd, 2009 at 10:43 am
@Akshay: I don't have such article myself but just type 'customizing cqwp' in your favorite search engine and I'm sure you will find it very quickly
October 22nd, 2009 at 3:58 am
Hey this works great, thanks very much! It worked for me in MOSS 2007 SP1+ with a category field of type MultiChoice. I just had to strip out the #; characters that delimit the values in the <a tag that resides in Imtech.TagCloud.
Here's my template to remove the extra category characters: