Docstoc

Customizing the Content Query Web Part in SharePoint

Document Sample
Customizing the Content Query Web Part in SharePoint Powered By Docstoc
					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)
Applies to: Microsoft Office SharePoint Server 2007
Download the code samples that accompany this article: SharePoint Content Query Web
Part Examples
Contents

      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




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
<?xml version="1.0"?><webParts>
 <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
  <metaData>
    <type name="Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart,
    Microsoft.SharePoint.Publishing, Version=12.0.0.0,
    Culture=neutral, PublicKeyToken=71e9bce111e9429c"/>
    <importErrorMessage>Cannot import this Web
    Part.</importErrorMessage>
  </metaData>
  <data>
    <properties>
       <!-- 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"
      type=
      "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart
      +FilterChainingOperator, Microsoft.SharePoint.Publishing,
      Version=12.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c">And</property>
      <property name="Filter2ChainingOperator"
      type="Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart
      +FilterChainingOperator, Microsoft.SharePoint.Publishing,
      Version=12.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c">And</property>
    ...
    </properties>
   </data>
 </webPart>
</webParts>
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




   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.

CQWP Query UI
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




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




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




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




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




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.FilterField
QueryOperator 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




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.SortDirecti
on. 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




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




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




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'>]]>
</property>

  Note:

 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.


  Note:

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 a 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>
</xsl:template>
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" />
</xsl:template>
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"
select="concat($SiteUrl,$FeedPageUrl,'xsl=1&amp;Web=',$WebUrl,
'&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.config file'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.

Tools

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.

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

namespace CCBQ
{
  [Guid("85b88c85-0bd0-406f-a014-471175c4c4ae")]
  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).

				
DOCUMENT INFO