Customizing the Content Query Web Part in SharePoint Server 2007

Summary: Walk through how to customize the Content Query Web Part (CQWP) in Microsoft Office SharePoint Server 2007 to query content across multiple sites in a site collection and display the results in any way that XSL can support. Learn how to get similar results when customizing the CQWP does not meet your needs. (20 printed pages)

MVP Icon  Robert Bogue, Thor Projects

January 2010

Applies to: Microsoft Office SharePoint Server 2007

Download the code samples that accompany this article: SharePoint Content Query Web Part Examples


  • Introduction to SharePoint Content Query Web Part Customization

  • Scenario: Crafting Custom Queries for the Content Query Web Part

  • Customizing the Content Query Web Part Using the UI and the *.webpart File

  • Deriving a Class for the Content Query Web Part

  • Replacing the Content Query Web Part with SPSiteDataQuery or Search

  • Conclusion

  • Additional Resources

Introduction to SharePoint Content Query Web Part Customization

The Content Query Web Part (CQWP) in Microsoft Office SharePoint Server 2007 provides important features for SharePoint users. Office SharePoint Server Web Parts generally work on a single list or library. That means that when users are presented with information, they are seeing information from just one place. However, in most organizations there is a real need to aggregate content over multiple lists and libraries and to present this content to the user in a single, unified view. Situations such as rolling up news from multiple departments are all too common in most organizations.

Although it is certainly possible that you can write your own Web Part to query multiple lists, it is also possible that you can run into performance issues that can make your entire system less responsive. The CQWP is designed specifically to take advantage of the SharePoint platform and to be minimally intrusive from a performance and scaling perspective. This design includes use of the SPSiteDataQuery objects to execute one search on an entire site collection and the extensive use of caching.

The core benefit of the CQWP is to aggregate content from all of the subsites, lists, and libraries so that the content can be displayed in a single view. After the data is queried and returned, the view is rendered by using a set of XSL templates to transform the data into HTML. The CQWP is flexible in its ability to change the XSL—and therefore the display generated by the CQWP—and in the options it provides for querying the information from the site.

With the ability to limit the query to a list type, a content type, and a subtree of URLS, the CQWP already provides a lot of flexibility directly from the UI (UI). In addition, you can export the CQWP and directly change some of the information that is not in the UI, enabling you to create custom queries for the CQWP to use.

Scenario: Crafting Custom Queries for the Content Query Web Part

This article examines creating custom queries for the CQWP, and how the impact of its architecture can affect how you can and cannot use it. In this example, two departments—public relations (PR) and human relations (HR) —both need to communicate with the employees of the organization on the home page. Instead of having two Web Parts on the home page, one with PR information and the other with HR information, the organization decides to include content from both departments on the home page in the same Web Part. Each department will also have a Web Part on its home page that shows only its news.

To start, both the HR and PR sites are subsites of a single site collection. The news for both PR and HR will be based on child content types of a News content type. All of the content types will be set up in the root of the site collection. HR will have an Internal News content type and PR will have a Press Release content type. With this configuration the news from the sites can be rolled up by using the UI of the CQWP.

The HR site will have more subsites from which news will roll up to the home page, but HR does not want the subsites on the HR home page. This will require editing the properties that cannot be modified through the UI by editing the *.webpart file. The HR department also wants to display news for a custom date range, which requires extending the CQWP to accept parameters.

Finally, we look at a scenario where there is a separate site collection for HR and PR, so the CQWP will not be able to roll up news. Instead, we can replace the CQWP with the SPSiteDataQuery object or search—alternatives which support content from separate site collections.

Customizing the Content Query Web Part Using the UI and the *.webpart File

The UI for the CQWP is the familiar tool pane interface that is used with all Web Parts. The interface is designed to enable the most common query and presentation options and the standard Web Part options, such as title and chrome. Despite the flexible UI for the CQWP, several properties and complex configurations are not available. For certain settings, you must export the Web Part and edit the *.webpart file manually. As you may know, a *.webpart file is an XML file that contains the information needed to load and configure the actual WebPart object.

SharePoint Server enables you to export the configuration of most Web Parts by selecting Export from the Web Part menu, as shown in Figure 1.

Figure 1. Web Part edit menu

Web Part edit menu

By selecting Export, you can save the configuration of the Web Part into a *.webpart file, which is simply an XML file with the class (.NET type) to load, and the configuration for that type. Many Web Parts have properties in their *.webpart files that are not shown in the UI. As an example, the following code shows the output from a CQWP. In this listing, the individual properties are reordered to improve readability and XML comments are added to make it easier to locate the properties of the CQWP as I describe them in this article.

<?xml version="1.0"?><webParts>
  <webPart xmlns="">
      <type name="Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart, 
      Microsoft.SharePoint.Publishing, Version=, 
      Culture=neutral, PublicKeyToken=71e9bce111e9429c"/>
      <importErrorMessage>Cannot import this Web 
          <!-- Properties from ContentByQuery -->
          <!-- ContentByQuery - Property Overrides -->
        <property name="ListsOverride" type="string"/>
        <property name="QueryOverride" type="string"/>
        <property name="ViewFieldsOverride" type="string"/>
        <property name="WebsOverride" type="string"/>

          <!-- Overriden by ListsOverride -->
        <property name="ServerTemplate" type="string">850</property>

          <!-- Overriden by QueryOverride -->
        <property name=
        "AdditionalFilterFields" type="string" null="true"/>
        <property name=
        "AdditionalGroupAndSortFields" type="string" null="true"/>
        <property name="BaseType" type="string"/>
        <property name="ContentTypeBeginsWithId" type="string"/>
        <property name=
        "ContentTypeName" type="string">Article Page</property>
        <property name="Filter1ChainingOperator" 
        +FilterChainingOperator, Microsoft.SharePoint.Publishing, 
        Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c">And</property>
        <property name="Filter2ChainingOperator" 
        +FilterChainingOperator, Microsoft.SharePoint.Publishing, 
        Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c">And</property>

After you have a *.webpart file and have made the changes that you want, you can import the *.webpart files into SharePoint Server.

To import a *.webpart file

  1. To place the page in Edit mode, on the Site Actions menu, click Edit Page.

  2. Click an Add a Web Part button on one of the Web Part zones on the page.

  3. In the Add Web Parts dialog box that opens, click the Advanced Web Part gallery and options link.

  4. In the catalog zone that appears on the right, click the drop-down arrow to the right of Browse, and then click Import, as shown in Figure 2.

    Figure 2. Catalog Zone Import menu

    Catalog Zone Import menu

  5. In the catalog zone, click Browse to open the Windows common file dialog box. Select your *.webpart file, and then click Open.

  6. Click Upload.

  7. After the *.webpart file is uploaded, click Import.

Modifying the UI properties drives changes in the *.webpart file, and using the *.webpart files offers a convenient way to reuse the configuration settings whether or not you need to make direct changes to the file. The following sections review the major areas of the tool pane and how you can use these to change the properties you find in the *.webpart file.


The Query UI of the tool pane includes sections for the source, list type, content type, audience targeting, and filters. These sections enable the CQWP to construct and execute a query by creating an instance of an SPSiteDataQuery object.

Source Section

The Source section shows three sources that the CQWP can use, as shown in Figure 3.

Figure 3. Source section UI

Source section UI

This section enables the user to select areas of the site collection (or another site collection) to include in the search and sets the WebUrl and ListGuid properties of the CQWP. When you select the first option, to search within the current site collection, neither the WebUrl nor the ListGuid is assigned a value. If the second item is selected, to get items from another site, the WebUrl is set to the selected site. If you select the third option, to get items from a specific list, the WebUrl is set to the Web site containing the list and the list's GUID is added to the ListGuid property. The WebsOverride property, discussed in detail later in this article, is not included in the UI. It would enable you to control whether only the Web is searched or whether the entire site collection is searched when the ListGuid is not present.

List Type Section

The List Type section enables you to select the type of list to include results from, as shown in Figure 4. These options filter the results to only those items found in the specified types of lists.

Figure 4. List Type section UI

List Type section UI

This list includes only the default templates and sets the ServerTemplate property of the CQWP. However, you can manually set the ServerTemplate property to the GUID of the feature that installs your custom list, or override the entire SPSiteDataQuery.Lists property by setting the ListsOverride property in the *.webpart file, as described later in this article.

Content Type Section

Perhaps the most powerful option within the CQWP is the ability to filter results by a content type and the child content types. Figure 5 shows the three-part identification of content types that exists in the Content Type UI.

Figure 5. Content Type section UI

Content Type section UI

The first selection to make is the group to which the content type belongs. This filters the second drop-down list, which shows the available content types. Unlike the List Type drop-down list, which shows only built-in lists, the Content Type group and items drop-down lists show all of the content types in the current site. The final check box indicates whether to include child content types and changes the property that is set in the CQWP. If the Include child content types check box is selected, the ContentTypeBeginsWithId property is set to the content type identifier (ID) for the content type. If the check box is not selected, the ContentTypeName property is set. The CQWP will execute a query with the "begins with" operator against the ContentTypeId for the value in the ContentTypeBeginsWithId property, or an "equal" operator against the ContentType for anything in ContentType name.

Including child content types is a great way to limit your results to a type of content while enabling users and other developers to derive from your content types. For example, you can filter to the News content type while allowing the HR department to have their own HR news content type that is derived from the News content type.

Audience Targeting Section

One of the key features in SharePoint Server is the ability to target information to users. You can do this by using Web Part targeting, where only certain sets of users can see a Web Part. You can also do it by specifying audiences on the information itself. The CQWP can process this audience targeting information when returning information to users. As shown in Figure 6, the Audience Targeting section consists of two check boxes.

Figure 6. Audience Targeting section UI

Audience Targeting section UI

The first check box sets the FilterByAudience property. The second check box sets the ShowUntargetedItems property. As the property name implies, setting a target for content is not required. By selecting this check box, you can show untargeted content. In most cases, untargeted content is intended for all users.

Additional Filters Section

The place to provide filtering on a per-field-value basis is the Additional Filters section. This section enables you to logically "and" or logically "or" up to three individual field queries together. Figure 7 shows the UI for these filters.

Figure 7. Additional Filters section UI

Additional Filters section UI

Each one of the filters sets four fields. The first field, for example, sets FilterField1, FilterType1, FilterOperator1, and FilterValue1. FilterField is the GUID for the site column to match to. The FilterType is type of the field from the SPFieldType enumeration. The FilterOperator is one of the values from the Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart.FilterFieldQueryOperator enumeration. One other set of properties are controlled by this block—the Filter?ChainingOperator fields (where ? is 1 or 2). These are the operators that "or" or "and" the values in the filtered fields together.

In addition to the filtering for content types, these basic combinations can handle most query needs. However, if the query need for the Web Part is complex, you can override the query altogether, including both the filtering here and the sorting and grouping described in the following section, by setting the QueryOverride property.

CQWP Presentation Group UI

The Presentation group consists of a Grouping and Sorting section, a Styles section, and a Feed section.

Grouping and Sorting Section

The Grouping and Sorting section, as shown in Figure 8, orders the results that are returned from the query.

Figure 8. Grouping and Sorting section UI

Grouping and Sorting section UI

The initial Group items by option controls which field is used to group items together. This is set in the GroupBy field as the GUID of the field. The GroupByFieldType is also set to the SPFieldType enumeration value for the type of field that is being used.

The direction of grouping is specified in the GroupByDirection field as a value from the enumeration Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart.SortDirection. The number of columns, which is used in the presentation of the results, is stored in the DisplayColumns property.

The next section for sorting uses the properties SortBy, SortByFieldType, and SortByDirection with the same types of values as were used for the grouping fields.

The last group of items in this section enable you to limit the maximum number of records returned, which sets the ItemLimit property that is provided to SPSiteDataQuery as RowLimit. This is particularly useful when you want to show only a few items, such as on the home page.

Styles Section

The Styles section provides two drop-down lists for selecting the group and styling items, as shown in Figure 9.

Figure 9. Styles section UI

Styles section UI

The Styles section sets the GroupStyle and ItemStyle properties, which are used to select which formatting template in the XSL files to use to display the results. The structure of the XSL files and how these values relate are described in detail in Customizing the User Experience.

Feed Section

The final section in the Presentation group, Feed, enables the user to control the visibility of a feed link and the feed's title and description, as shown in Figure 10.

Figure 10. Feed section UI

Feed section UI

The Feed section sets the FeedEnabled property to true or false. It also sets the FeedTitle and FeedDescription properties to the values provided.

Changing the CQWP Query

The preceding section describes how UI changes drive changes in the properties of the CQWP, and how you can use those settings to create queries that return the results you need. However, the CQWP is extensible beyond the capabilities of the UI. Figure 11 shows the properties of the CQWP and their relationship to the SPSiteDataQuery object that the CQWP uses. The green boxes are properties that can be set from the UI and the blue boxes are properties that must be set by directly editing the Web Part file. In the diagram, you can see how many individual properties that are set in the UI roll up into a set of properties that are used for the SPSiteDataQuery object. In addition to being able to manually set the values that can be set through the UI, you can also set "override" properties that will override the normal generation of the fields that the SPSiteDataQuery needs.

Figure 11. CQWP properties and their relationship to SPSiteDataQuery

CQWP property relationships to SPSiteDataQuery

The UI provides a set of properties that should meet the needs of most casual users. The additional properties that are available through the *.webpart file enable more powerful settings that cannot be specified in the UI.

The first property, QueryOverride, is used to override the actual Collaborative Application Markup Language (CAML) that is being executed. The properties WebsOverride and ListsOverride provide important controls on whether subsites are crawled and the lists to include in the search. The properties CommonViewFields and ViewFieldsOverride are used to control what fields are returned in the results set. This is necessary so that the XSL (discussed in the next section) has the additional information needed to be able to display.

QueryOverride Property

When executing a query via SPQuery or SPSiteDataQuery, you can provide a CAML fragment that specifies the query (equivalent to the SQL WHERE clause) and the order (equivalent to the SQL ORDER BY clause). These two CAML fragments control the results that are returned and their order. By default, the CQWP builds this CAML query from the fields specified in the UI. However, by setting the QueryOverride property in the *.webpart file, you can manually specify these values.

This is useful when you need to include multiple content types that do not have the same parent or include results filtered by more than three fields, or in cases where you want to provide more than one sorting field. Any query that can be executed by SPSiteDataQuery can be supplied to QueryOverride.

Because the properties in the XML file cannot contain embedded XML, any CAML that you need to add to a property must either be encoded or enclosed within a <CDATA> tag which begins with <![CDATA[ and ends with ]]>.

Setting the QueryOverride causes the CQWP to ignore all of the filtering, grouping, and sorting options that are set in the UI.

WebsOverride Property and ListsOverride Property

By default, the CQWP executes its searches across an entire site collection, however, you can prevent CQWP from recursing sites. You do this by overriding the WebsOverride property and setting it to <Webs />. If you want to specify the value of the property and allow subsites, you can specify <Webs Scope='Recursive'/>, which will recurse subsites. You can also set the value to <Webs Scope='SiteCollection' /> so that all results from the site collection are returned.

The ListsOverride property is created by the CQWP normally by using the ServerTemplate value that is specified in the UI. However, the SPSiteDataQuery that the CQWP uses has a default that limits the maximum number of lists that can return data to 1,000. There may be situations where this value must be overriden. If so, you set the ListsOverride exactly as you would provide the value to the SPSiteDataQuery.List property. To limit the search to pages libraries and specify a maximum of 2,000 lists, the value would be as follows.

<Lists ServerTemplate='805' MaxListLimit='2000' />

In the *.webpart file, this would look like the following.

<property name="ListsOverride" type="string">
  <![CDATA[<Lists ServerTemplate='805' MaxListLimit='2000'>]]>


The more lists that the CQWP looks through, the longer the query will take. Because of this, you may need to reconsider your design if you are going to have thousands of lists that the CQWP needs to scan.

CommonViewFields and ViewFieldsOverride

After you get the right rows back, it is important to get the right information in those rows. If the information is not in the row, the XSL cannot display it to the user. The CQWP offers two key ways to do this: CommonViewFields and ViewFieldsOverride.

CommonViewFields is a simpler way to add fields because the value in CommonViewFields is the internal name of the field followed by a comma and its type from SPFieldType. Individual fields are separated by semicolons. CommonViewFields is also simpler than ViewFieldsOverride because you do not have to reference all of the fields that the CQWP includes by default. Even without any field settings, the CQWP will include a default set of fields that the XSL expects to receive.

Using the ViewFieldsOverride property is more challenging because it requires that you include all of the default fields plus the fields you want to add. However, if you want to add the title of a site or list to the output, it is the only way to accomplish this. If you want to add your own fields via ViewFieldsOverride, you can start by adding the following and simply appending your fields. The following represents all of the fields that are included natively by CQWP.

<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Nullable="True" Type="Text" /> <!-- Title -->
<FieldRef ID="{94f89715-e097-4e8b-ba79-ea02aa8b7adb}" Nullable="True" Type="Lookup" /> <!-- FileRef -->
<FieldRef ID="{1d22ea11-1e32-424e-89ab-9fedbadb6ce1}" Nullable="True" Type="Counter" /><!-- ID -->
<FieldRef ID="{28cf69c5-fa48-462a-b5cd-27b6f9d2bd5f}" Nullable="True" Type="DateTime" /><!-- Modified -->
<FieldRef ID="{1df5e554-ec7e-46a6-901d-d85a3881cb18}" Nullable="True" Type="User" /><!-- Author -->
<FieldRef ID="{d31655d1-1d5b-4511-95a1-7a09e9b75bf2}" Nullable="True" Type="User" /><!-- Editor -->
<FieldRef ID="{8c06beca-0777-48f7-91c7-6da68bc07b69}" Nullable="True" Type="DateTime" /><!-- Created -->
<FieldRef ID="{543bc2cf-1f30-488e-8f25-6fe3b689d9ac}" Nullable="True" Type="Image" /> <!-- PublishingRollupImage -->
<FieldRef ID="{43bdd51b-3c5b-4e78-90a8-fb2087f71e70}" Nullable="True" Type="Number" /> <!-- Level -->
<FieldRef ID="{9da97a8a-1da5-4a77-98d3-4bc10456e700}" Nullable="True" Type="Note" /> <!-- Comments -->
<FieldRef ID="{61cbb965-1e04-4273-b658-eedaa662f48d}" Nullable="True" Type="TargetTo" /><!-- Audience -->

Notice the Nullable="True" attribute. This tells the CQWP that the row can be returned even if the row does not contain the field. For your fields, you may or may not want to filter the results based on whether the field you are attempting to return exists in the row. Also, notice that you do not want to include the XML comments in the preceding listing in your actual ViewFieldsOverride because the SPSiteDataQuery that CQWP uses does not allow comments in the CAML for view fields. The preceding comments are designed to help you understand what the GUID refers to.

In addition to your own FieldRefs, you can also add the name of the site and the name of the list that the item came from by adding <ProjectProperty Name="Title"/> and <ListProperty Name="Title"/> to the ViewFieldsOverride. These fields will appear in the output as ProjectProperty.Title and ListProperty.Title, respectively. These fields can be useful if you want to show where the data came from.


With any of these changes you may need to ensure that you see your changes. For performance reasons, by default the CQWP caches the output of the query so that it does not have to query SharePoint Server again for the matching results. You can avoid this by leaving the page in Edit mode, because the CQWP never uses the cache when the page is in Edit mode, or by setting the UseCache property in the *.webpart file to false. Be sure to reset the UseCache property to true (or blank) before you put the Web Part into production to maintain performance.

For more information about displaying additional fields in the CQWP, see How to Display Custom Fields in the Content Query Web Part.

Customizing the User Experience

Now that the query is returning the right results, you can transform those results into the HTML that the users expect. That requires working with the three XSL files that the CQWP uses to transform the data into HTML, knowing what the data that is returned looks like, and having a set of knowledge and tools to make the process easier.

How CQWP Transforms Data into HTML

The SPSiteDataQuery that the CQWP uses to query can easily translate the results into an XML stream. After the results are in an XML stream, you can use the industry-standard XSL to transform the XML in to HTML for display. Transforming XML to HTML is generally performed with one XSL file but to maintain consistency between the three publishing Web Parts that transform information (Summary Links and Table of Contents are the other two) and to minimize the amount of XSL in one file, CQWP uses three different XSL files in the transformation. The properties and the files for these are:

  • MainXslLink   By default, points to ContentQueryMain.xsl in the Style Library. This is the starting point for the XSLT transformation.

  • HeaderXslLink   By default, points to Header.xsl in the Style Library. Header.xsl is responsible for the group styling. To add new group styling options you add it to this file.

  • ItemXslLink   By default, points to ItemStyle.xsl in the Style Library. ItemStyle.xsl is responsible for individual row styling. New row styling options are added to this file.

Understanding how these three files work together to render the HTML output is essential because the CQWP has dependencies on specific items in the XSL files. That makes using simple XSL techniques to dump out the incoming XML more difficult.

The processing flow for the XSLT transformation starts in the ContentQueryMain.xsl (file pointed to by MainXslLink) with a match for "/" (the root node), which directly calls the OuterTemplate template. OuterTemplate determines whether the result set is empty. If it is empty and the mode is Edit, it displays the message that the CQWP passed in as a variable. If, however, the result set is not empty, OuterTemplate calls the OuterTemplate.Body template. In either case, if the feed is enabled then the feed is added.

TheOuterTemplate.Body template organizes the results into groups and columns. It does this by calling OuterTemplate.CallHeaderTemplate and OuterTemplate.CallFooterTemplate at the appropriate times. It adds hard-coded separators for the columns between items as needed.

OuterTemplate.CallHeaderTemplate calls the appropriate template in Header.xsl by using <xsl:apply-templates> with the current node and a mode of "header". In the header.xsl file pointed to by the HeaderXslLink property, the templates include a match criteria that tests the value of the GroupStyle attribute and a mode of "header". Thus, OuterTemplate.CallHeaderTemplate calls the correct group styling in the header file. The mode attribute of <xsl:template> and the mode attribute of <xsl:apply-templates> match and ensure that the matching template is only one of the header templates.

OuterTemplate.CallFooterTemplate does not call any templates, but instead emits a static <div> tag with an identifier of "footer".

After OuterTemplate.Body has made the appropriate calls for grouping, it makes a call to OuterTemplate.CallItemTemplate, which in turn calls templates in the itemstyle.xsl file pointed to by the ItemXslLink property. It does this, generically, by using <xsl:apply-templates> with a mode of "ItemStyle". The <xsl:templates> in the ItemStyle.xsl include the same mode of "ItemStyle" and a match for the Style attribute. The ContentQueryMain provides for specific handling for NewsRollUpItem, NewsBigItem, and NewsCategoryItem styles because the templates for these styles require additional parameters.

In addition to the templates mentioned previously, there are numerous other templates in the three files that are used for string processing and other utility purposes.

Raw XML Results

Knowing how the data is processed at a high level is a big start to developing your own group and item styles. However, not knowing exactly what the data looks like coming into an XSLT transformation can make building and debugging problems nearly impossible. In most applications of XSLT transformation, you can simply create an XSL file that contains the following.

<xsl:template match="/">
  <xmp><xsl:copy-of select="*" /></xmp>

This code says, effectively, match the root element and select everything inside it and dump it out. The <xmp> tag is an obsolete HTML tag that renders everything inside it instead of trying to decode it as additional markup. This prevents the need to escape all of the output of the XML for display on an HTML page.

If you replace ContentQueryMain.xsl with just this, you get an error from the CQWP. This is because CQWP expects certain pieces of the ContentQueryMain.xsl file to be available, including the incoming parameters. To dump the raw XML, you would not replace the entire ContentQueryMain.xsl file. Instead, you would replace the existing XSL template that matches the root node. On line 27 of the ContentQueryMain.xsl, you should see the template which looks like the following.

<xsl:template match="/">
  <xsl:call-template name="OuterTemplate" /> 

When you change this to the XSL provided earlier, the output of the CQWP should now be the raw XML provided as input. Of course, making a change to ContentQueryMain.xsl in production is a bad idea because suddenly every CQWP will start dumping out the raw XML instead of the transformed content. That's why it's important to be able to reference a different XSL file for your CQWP, especially for testing.

Referencing Different XSL

The previous section provided the properties in the CQWP that referenced the three files that CQWP uses. These properties are essential so that you can create CQWP instances where the display is unique for a site. By copying the existing ContentQueryMain.xsl, Header.xsl, and ItemStyle.xsl into your files and changing the MainXslLink, HeaderXslLink, and ItemXslLink properties of your CQWP's *.webpart file, you can work on a completely separate set of styles from those provided by default. You can also avoid the potential that an update will overwrite your hard work.

While the XSL files for most of the transformation just require changes to the CQWP properties in the *.webpart file, making changes to the Really Simple Syndication (RSS) feed and how it is displayed is a bit more complicated.

Changing the RSS Feed for the CQWP

Each CQWP in SharePoint Server can expose an RSS feed. RSS feeds are readable through a set of RSS reader programs, including the RSS reader included in Internet Explorer 7 (and Internet Explorer 8) and in Outlook 2007. RSS feeds from CQWPs enable you to create news feeds for your site that mirror the items in the CQWPs on the site and that are cached like a regular CQWP.

The RSS feed is enabled through the UI as described earlier. The output of the RSS feed from the CQWP is customizable beyond the title and description available in the UI. To customize the RSS feed, you need to understand how the RSS is link is created.

On line 54 of the ContentQueryMain.xsl is a definition for a variable named FeedUrl1 as shown here.

<xsl:variable name="FeedUrl1" 
'&amp;page=',$PageId,'&amp;wp=',$WebPartId)" />

The SiteUrl and FeedPageUrl are parameters that the CQWP passes into the XSL. The SiteUrl is the URL of the current site and the FeedPageUrl is _layouts/feeds.aspx. In the previous code, you can see that the Web, page, and WebPartId are passed into the RSS page, Feeds.aspx. These parameters allow the page to get an instance of the CQWP Web Part from the SPLimitedWebPartManager. By doing this it can get the query results back from the CQWP. This is how the page will fetch the data necessary for the RSS feed results. The additional parameter on the query string which is not needed to fetch the results is an XSL parameter. This parameter sets which XSL will be used to transform the results from the CQWP into the RSS feed.

The value provided in the XSL parameter matches entries in the web.configfile's <appSettings> tag. By default SharePoint includes the following entry in the web.config of the Web applications it creates.

<add key="FeedXsl1" value="/Style Library/Xsl Style Sheets/Rss.xsl" >

The value here is two parts: the prefix of FeedXsl and the suffix of 1, which matches the default XSL parameter passed into the Feeds.aspx. The value can be any value provided to the feeds.aspx page, alphabetical or numeric. Obviously, modifying the web.config file of SharePoint Server is problematic, particularly in a farm, so modifying the RSS feed requires extra configuration management than the previously described solutions for changing the output of the CQWP directly.

To change the way that RSS feeds are generated:

  1. Create a new Rss.xsl with the changes.

  2. Add an <appSettings> entry for the new Rss.xml file with a new suffix.

  3. Create a new ContentQueryMain.xsl with a new XSL parameter.

  4. Customize the *.webpart for the CQWP to reference the new ContentQueryMain.xsl file.

You can use these steps to customize the output of the RSS to include only parts of the articles, or to inject other parts of the RSS standard that the built-in transformation does not provide.

For more information about customizing the RSS feed, see How to Customize RSS for the Content Query Web Part.

Working with XSL

If you do not work with XSL every day, it can be a daunting task to stare at the over 600 lines of XSL that make up the three XSL files that CQWP uses to transform the query results and start to work with them. Fortunately, there are tools and references that you can use to make the XSL editing process easier.


Microsoft's development platform, Microsoft Visual Studio (2005 or later), includes an XML editor with XSL support. The editor includes the ability to view the XSL output and the ability to debug the XSL. Admittedly, the capabilities of Visual Studio to run the XSLT transformation is of limited use because the dependencies between the CQWP and the XSL make it impossible to run the XSL outside of the CQWP.

Microsoft Office SharePoint Designer 2007 also includes an XML and XSL editor you can use to modify the XSL files that the CQWP uses. The benefit of SharePoint Designer as an XML or XSL editor is that it can save files directly into SharePoint Server. This can make the editing cycle for making changes to the CQWP easy.

Finding XSLT References

If you are trying to learn XSL and need a reference guide, Microsoft provides a complete XSLT Reference. You can also use the article How to: Customize XSL for the Content Query Web Part for a step-by-step walkthrough of the customization process.

Troubleshooting CQWP Issues

CQWP issues can really occur in one of two parts. The first part, and where most trouble can occur, is in the query generation. However, problems can occur during the second part, the creation of the view.

Query Generation

Because the CQWP is using SPSiteDataQuery and you an override the CAML used to execute the query, the results from CQWP exhibit the same exacting precision as the SPSiteDataQuery object. This means that a single error in one of the CAML values that you can override—WebsOverride, ListsOverride, QueryOverride, or ViewFieldsOverride—can mean that you will get an error or more likely simply get no results.

The easiest thing to do is to check your results with a direct call to SPSiteDataQuery to see if there is an error returned, and to make quick changes to values to see if you can determine the issue. The code provided as a part of this article includes a Web Part that calls SPSiteDataQuery and exposes the four fields so that they can be edited in the UI. You can use this tool to see how the SPSiteDataQuery is responding to the CAML fragments that you provide to it.

One of the most common problems is not referring to a field by its internal name. Referring to a field by its display name leads to an error.

View Generation

View generation issues generally fall into two categories. Either the field that you're trying to use is not available because it has a different name or was not included, or the XSL that you are using to create the display is incorrect.

Most frequently the field is not included in the ViewFieldsOverride. To verify that you are receiving the data you expect, you can replace your XSL with the XSL discussed earlier in the section Raw XML Results.

Deriving a Class for the Content Query Web Part

The CQWP, also known as Microsoft.SharePoint.Publishing.WebControls.ContentByQuery, is not a sealed class. This means that classes can be derived from it and can thereby be extended with additional new functionality. One of the common requests for the CQWP is to be able to parameterize the query so that one CQWP can be used to serve different content based on the page or a query string parameter. To demonstrate this. you can derive a class from the CQWP and add the ability to do Web Part connections for the three filter values that the CQWP can accept. The following code example shows that deriving a class from the CQWP is straightforward.

using System;
using System.Runtime.InteropServices;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing.WebControls;

namespace CCBQ
    public class CCBQ : ContentByQueryWebPart
        [ConnectionConsumer("Filter 1 Value", "Filter1Value" )]
        public void ConnectedFilter1Value(IWebPartField field)
            field.GetFieldValue(delegate(object val) { FilterValue1 = (string)val; });
        [ConnectionConsumer("Filter 2 Value", "Filter2Value")]
        public void ConnectedFilter2Value(IWebPartField field)
            field.GetFieldValue(delegate(object val) { FilterValue2 = (string)val; });
        [ConnectionConsumer("Filter 3 Value", "Filter3Value")]
        public void ConnectedFilter3Value(IWebPartField field)
            field.GetFieldValue(delegate(object val) { FilterValue3 = (string)val; });

When placed on a page, you can connect this Web Part to an instance of the QueryString (URL) Filter Web Part to retrieve the value from the query string and pass it to the CQWP. It is also possible to set another filter Web Part on the page which the user types into to filter the data returned from the CQWP.

In our scenario, by using this extended Web Part you can enable the content owners to create their own pages with custom date ranges. The result is a page that can be used for multiple seasons based on values provided by the content owners.

Replacing the Content Query Web Part with SPSiteDataQuery or Search

Although the CQWP is very powerful, it does not fit every situation. In some cases it might be necessary to use other tools for searching, for example, in a situation that requires you to return data from several site collections. The CQWP would not work for you because CQWP returns information from one site collection, so in this case you could write your own Web Part that used multiple SPSiteDataQuery calls and aggregated the results, or you could use the powerful SharePoint Server search functionality to return results.

Deciding whether to use multiple SPSiteDataQuery calls or one search call should be based on two key factors, urgency of updates and performance. Using search requires less resources but will also suffer from a lag between when the item is published and when it is indexed by crawling. Executing multiple SPSiteDataQuery calls allows for more up-to-date information, but means a higher load on the system due to the multiple calls.

If you decide that the best path is to use SPSiteDataQuery, you will find that your WebsOverride is the Webs property, ListsOverride is the Lists property, QueryOverride is the Query property, and the ViewFieldsOverride is the ViewFields property; these are the properties that you must set to execute an SPSiteDataQuery query. This plus RowLimit, and knowing which SPWeb object on which to run the query (the WebUrl) are all that is needed to perform the query portion of the CQWP's job.

If you decide to use the search approach, there are a few more steps that you have to complete from an infrastructure perspective, but the code itself is relatively straightforward. To use the search features in SharePoint Server, the data must be set up as a managed property through the Shared Services Provider (SSP). After setting up the properties to be returned and the properties to be queried, you can execute a search and get results. For more information, see: Search Customization and Development Options in SharePoint Server 2007 and the white paper Managing Enterprise Metadata with Content Types.

If you are interested in seeing SPSiteDataQuery in action and ways that you can use the search system, see SharePoint Search Keyword and SQL Full Text Example (MSDN Code Gallery).


The Content Query Web Part (CQWP) is an amazingly flexible tool for querying and displaying data. From the ease of use provided by the user interface to a set of Web Part properties that enable full control of the query, caching, and display of results—the tool can be customized by the end user, business analyst, and developer. Deriving classes from the CQWP gives you the ability to add new features quickly and easily, such as data connections or paging. A fully customizable XSLT-based transformation of the query results means that you can display the results you get back. In addition, the SharePoint platform provides alternatives for those situations where the CQWP does not meet the needs of your scenario. You can make calls to the same interface that CQWP uses in the SPSiteDataQuery object, or alternatively by using the SharePoint Server search infrastructure.

Additional Resources

For more information, see the following resources: