Showing posts with label MOSS Search. Show all posts
Showing posts with label MOSS Search. Show all posts

Thursday, September 24, 2009

The MOSS Search Saga: Modifying the advanced search page

In a previous post of mine I explained how to create managed properties and modify the search results page for a custom Protocol application. In this post I am going to continue from my previous example by modifying the advanced search tab.

The idea is to modify the search page in order to include some of my managed properties in the search query logic, add the “contains” and “does not contain” equation in my search expressions and limit the language query options to English an Greek only.

  • I navigate to the advanced search page and I go into edit page mode
    image
  • I select the edit menu of the Advanced Search Box webpart and the Modify Shared Web part option
    image
  • In the Advanced Search Box –> Properties –> I pres the … icon in the Properties field
    image
  • A new window appears with the XML format of the advanced search properties

    <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance%22>
    <Option Name="AllowOpContains" Value="False"/>
    <LangDefs>
    <LangDef DisplayName="Arabic" LangID="1"/>
    <LangDef DisplayName="Bengali" LangID="69"/>
    <LangDef DisplayName="Bulgarian" LangID="2"/>
    <LangDef DisplayName="Catalan" LangID="3"/>
    <LangDef DisplayName="Chinese" LangID="4"/>
    <LangDef DisplayName="Croatian/Serbian" LangID="26"/>
    <LangDef DisplayName="Czech" LangID="5"/>
    <LangDef DisplayName="Danish" LangID="6"/>
    <LangDef DisplayName="Dutch" LangID="19"/>
    <LangDef DisplayName="Finnish" LangID="11"/>
    <LangDef DisplayName="French" LangID="12"/>
    <LangDef DisplayName="German" LangID="7"/>
    <LangDef DisplayName="Greek" LangID="8"/>
    <LangDef DisplayName="Gujrati" LangID="71"/>
    <LangDef DisplayName="Hebrew" LangID="13"/>
    <LangDef DisplayName="Hindi" LangID="57"/>
    <LangDef DisplayName="Hungarian" LangID="14"/>
    <LangDef DisplayName="Icelandic" LangID="15"/>
    <LangDef DisplayName="Indonesian" LangID="33"/>
    <LangDef DisplayName="Italian" LangID="16"/>
    <LangDef DisplayName="Japanese" LangID="17"/>
    <LangDef DisplayName="Kannada" LangID="75"/>
    <LangDef DisplayName="Korean" LangID="18"/>
    <LangDef DisplayName="Latvian" LangID="38"/>
    <LangDef DisplayName="Lithuanian" LangID="39"/>
    <LangDef DisplayName="Malay" LangID="62"/>
    <LangDef DisplayName="Malayalam" LangID="76"/>
    <LangDef DisplayName="Marathi" LangID="78"/>
    <LangDef DisplayName="Norwegian" LangID="20"/>
    <LangDef DisplayName="Polish" LangID="21"/>
    <LangDef DisplayName="Portugese" LangID="22"/>
    <LangDef DisplayName="Punjabi" LangID="70"/>
    <LangDef DisplayName="Romanian" LangID="24"/>
    <LangDef DisplayName="Russian" LangID="25"/>
    <LangDef DisplayName="Slovak" LangID="27"/>
    <LangDef DisplayName="Slovenian" LangID="36"/>
    <LangDef DisplayName="Spanish" LangID="10"/>
    <LangDef DisplayName="Swedish" LangID="29"/>
    <LangDef DisplayName="Tamil" LangID="73"/>
    <LangDef DisplayName="Telugu" LangID="74"/>
    <LangDef DisplayName="Thai" LangID="30"/>
    <LangDef DisplayName="Turkish" LangID="31"/>
    <LangDef DisplayName="Ukrainian" LangID="34"/>
    <LangDef DisplayName="Urdu" LangID="32"/>
    <LangDef DisplayName="Vietnamese" LangID="42"/>
    </LangDefs>
    <Languages>
    <Language LangRef="12"/>
    <Language LangRef="7"/>
    <Language LangRef="17"/>
    <Language LangRef="10"/>
    </Languages>
    <PropertyDefs>
    <PropertyDef Name="Path" DataType="text" DisplayName="URL"/>
    <PropertyDef Name="Size" DataType="integer" DisplayName="Size"/>
    <PropertyDef Name="Write" DataType="datetime" DisplayName="Last Modified Date"/>
    <PropertyDef Name="FileName" DataType="text" DisplayName="Name"/>
    <PropertyDef Name="Description" DataType="text" DisplayName="Description"/>
    <PropertyDef Name="Title" DataType="text" DisplayName="Title"/>
    <PropertyDef Name="Author" DataType="text" DisplayName="Author"/>
    <PropertyDef Name="DocSubject" DataType="text" DisplayName="Subject"/>
    <PropertyDef Name="DocKeywords" DataType="text" DisplayName="Keywords"/>
    <PropertyDef Name="DocComments" DataType="text" DisplayName="Comments"/>
    <PropertyDef Name="Manager" DataType="text" DisplayName="Manager"/>
    <PropertyDef Name="Company" DataType="text" DisplayName="Company"/>
    <PropertyDef Name="Created" DataType="datetime" DisplayName="Created Date"/>
    <PropertyDef Name="CreatedBy" DataType="text" DisplayName="Created By"/>
    <PropertyDef Name="ModifiedBy" DataType="text" DisplayName="Last Modified By"/>
    </PropertyDefs>
    <ResultTypes>
    <ResultType DisplayName="All Results" Name="default">
    <Query/>
    <PropertyRef Name="Author"/>
    <PropertyRef Name="Description"/>
    <PropertyRef Name="FileName"/>
    <PropertyRef Name="Size"/>
    <PropertyRef Name="Path"/>
    <PropertyRef Name="Created"/>
    <PropertyRef Name="Write"/>
    <PropertyRef Name="CreatedBy"/>
    <PropertyRef Name="ModifiedBy"/>
    </ResultType>
    <ResultType DisplayName="Documents" Name="documents">
    <Query>IsDocument=1</Query>
    <PropertyRef Name="Author"/>
    <PropertyRef Name="DocComments"/>
    <PropertyRef Name="Description"/>
    <PropertyRef Name="DocKeywords"/>
    <PropertyRef Name="FileName"/>
    <PropertyRef Name="Size"/>
    <PropertyRef Name="DocSubject"/>
    <PropertyRef Name="Path"/>
    <PropertyRef Name="Created"/>
    <PropertyRef Name="Write"/>
    <PropertyRef Name="CreatedBy"/>
    <PropertyRef Name="ModifiedBy"/>
    <PropertyRef Name="Title"/>
    <PropertyRef Name="Manager"/>
    <PropertyRef Name="Company"/>
    </ResultType>
    <ResultType DisplayName="Word Documents" Name="worddocuments">
    <Query>FileExtension='doc' Or FileExtension='docx' Or FileExtension='dot'</Query>
    <PropertyRef Name="Author"/>
    <PropertyRef Name="DocComments"/>
    <PropertyRef Name="Description"/>
    <PropertyRef Name="DocKeywords"/>
    <PropertyRef Name="FileName"/>
    <PropertyRef Name="Size"/>
    <PropertyRef Name="DocSubject"/>
    <PropertyRef Name="Path"/>
    <PropertyRef Name="Created"/>
    <PropertyRef Name="Write"/>
    <PropertyRef Name="CreatedBy"/>
    <PropertyRef Name="ModifiedBy"/>
    <PropertyRef Name="Title"/>
    <PropertyRef Name="Manager"/>
    <PropertyRef Name="Company"/>
    </ResultType>
    <ResultType DisplayName="Excel Documents" Name="exceldocuments">
    <Query>FileExtension='xls' Or FileExtension='xlsx' Or FileExtension='xlt'</Query>
    <PropertyRef Name="Author"/>
    <PropertyRef Name="DocComments"/>
    <PropertyRef Name="Description"/>
    <PropertyRef Name="DocKeywords"/>
    <PropertyRef Name="FileName"/>
    <PropertyRef Name="Size"/>
    <PropertyRef Name="DocSubject"/>
    <PropertyRef Name="Path"/>
    <PropertyRef Name="Created"/>
    <PropertyRef Name="Write"/>
    <PropertyRef Name="CreatedBy"/>
    <PropertyRef Name="ModifiedBy"/>
    <PropertyRef Name="Title"/>
    <PropertyRef Name="Manager"/>
    <PropertyRef Name="Company"/>
    </ResultType>
    <ResultType DisplayName="Presentations" Name="presentations">
    <Query>FileExtension='ppt'</Query>
    <PropertyRef Name="Author"/>
    <PropertyRef Name="DocComments"/>
    <PropertyRef Name="Description"/>
    <PropertyRef Name="DocKeywords"/>
    <PropertyRef Name="FileName"/>
    <PropertyRef Name="Size"/>
    <PropertyRef Name="DocSubject"/>
    <PropertyRef Name="Path"/>
    <PropertyRef Name="Created"/>
    <PropertyRef Name="Write"/>
    <PropertyRef Name="CreatedBy"/>
    <PropertyRef Name="ModifiedBy"/>
    <PropertyRef Name="Title"/>
    <PropertyRef Name="Manager"/>
    <PropertyRef Name="Company"/>
    </ResultType>
    </ResultTypes>
    </root>

Let’s explore the XML in order to see how we can manipulate the advanced search box query properties:

  • To include the “contains” and “does not contain” equation in my search expressions I just need to edit the Option AllowOpContains (Red Text) from False to True.
  • To leave only the Greek and English language option in my languages search query, I have to edit the <Language LangRef=”Number”> tag (Orange Text) with the appropriate language definition number (Grey Text).
  • I check the language definitions list for the Greek language and I notice that the Greek definition is equal to “8” (Grey Text). I Remove all <Language LangRef=”Number”> tags and I leave only one; the one with the Greek language Definition <Language LangRef=”8”> (Orange Text).
  • To include my managed properties in search terms I have to add a property definition for my managed property (Blue Text) and a Property Reference (Green Text) for the appropriate definition to appear in the properties dropdown list.
  • To create a property definition for my ProtOurPID managed property, I have to include a <PropertyDef Name=”ProtOurPID” DataType=”Text” DisplayName=”Our PID”/> tag (Blue Text) where Name=”My managed property name”, DataType=”Data type (Text, DateTime, etc)”, DisplayName=”The appearance in the pick property drop down menu

    <PropertyDef Name="ProtOurPID" DataType="text" DisplayName="Our PID"/>
    <PropertyDef Name="ProtSubject" DataType="text" DisplayName="Subject"/>
    <PropertyDef Name="ProtINOUT" DataType="text" DisplayName="IN/OUT"/>
    <PropertyDef Name="ProtDocumentDate" DataType="datetime" DisplayName="Document Date"/>
    <PropertyDef Name="ProtINTOriginDestination" DataType="text" DisplayName="Internal Origin/Destination"/>
    <PropertyDef Name="ProtEXTOriginDestination" DataType="text" DisplayName="External Origin/Destination"/>
    <PropertyDef Name="ProtCommentsDescriptions" DataType="text" DisplayName="Protocol Comments / Description"/>
    <PropertyDef Name="ProtTheirPID" DataType="text" DisplayName="Their PID"/>

  • Finally, I need to be able to query my custom managed properties. In order to do so, I have to create a Property Reference for my Property Definitions I created earlier. I have the option to create groupings of Property References called Result Types. Result Types can have their own groupings of Property References and filtering queries. For example, to create a Result Type for my Protocol Lists I can add the following markup just before the </ResultTypes> closing tag:

    <ResultType DisplayName="Protocols" Name="Protocol">
    <Query>IsDocument=0</Query>
    <PropertyRef Name="ProtOurPID"/>
    <PropertyRef Name="ProtSubject"/>
    <PropertyRef Name="ProtINOUT"/>
    <PropertyRef Name="ProtDocumentDate"/>
    <PropertyRef Name="ProtINTOriginDestination"/>
    <PropertyRef Name="ProtEXTOriginDestination"/>
    <PropertyRef Name="ProtTheirPID"/>
    </ResultType>

  • This result type will query the results that are not documents “<Query>IsDocument=0</Query>” and will allow you to query only the grouping of the managed properties referenced in that particular result type.

You can always create more complex queries by adding OR and AND statements. Like:

<Query>FileExtension='xls' Or FileExtension='xlsx' Or FileExtension='xlt'</Query>

Friday, August 21, 2009

The MOSS Search Saga: Modifying The Search Results Page

The customization of the search experience in MOSS is crucial in many situations. You may need to add additional metadata to your display results, to modify the search result page layout or to add additional metadata properties to your advanced search page. In the paragraphs below I am going to demonstrate a simple scenario of MOSS search experience customization.

In the first part of this example I am going to create a tabular layout of my search results page for an e-protocol SharePoint list. I am going to demonstrate the way to add additional metadata to the search results page, to modify the layout using SharePoint Designer and in the second part to modify the advanced search page to include more options to query.

Before I start customizing my search results page I need to populate some custom columns, I created to my e-protocol SharePoint list. Each time SharePoint crawls the farm to create indexed content, it adds any custom column (metadata property) it finds in Lists, Document Libraries and Sites, to its metadata properties database. But for those properties to become manageable, MOSS administrator needs to create a “managed property” record for each of the metadata he needs to manage. Notice that each “managed property” can map to one or more metadata properties. For example, if I want to create a managed property for the ProtocolID metadata, I would create a single map for this property. This could become available to my search results page and advanced search queries. Now consider the following scenario: I want to create a single managed property to query and display all kinds of calling number information across my contacts lists. I should create a single managed property which maps to multiple metadata properties: mobile phone, home phone, company phone, etc.

I am going to create seven (7) managed properties for my Protocol Application List. In order to create these managed properties I need to navigate to the Search Administration Page of my SSP:

  • From there I navigate to the metadata properties in the side menu and I select new managed property.
  • I type an appropriate name for my new managed property (ex ProtID)
  • I select the appropriate type of this property (ex Text)
    image
  • I add the appropriate mapping by selecting a crawled metadata property to map to this managed property (ex ows_PID)
    image
  • Press the OK button

At this point I repeat the same procedure for the next six (6) managed properties I want to create:
image

From that point, I want to modify my search results page. In my search results page I want to display, in a tabular format, the ProtPID, ProtSubject, ProtINOUT, ProtDocumentDate, ProtNTOriginDestination and ProtEXTOriginDestination properties I have created in the previous steps. SharePoint server/services return the search results in an XML format. The visual presentation of this XML format is done by XSLT and CSS. So, in order to manipulate the visual representation of those results I have to extract their raw XML form.

To extract the raw XML form of my search results:

  • I navigate to my search center web site
  • I submit a search term in the search box (ex Test)
  • In the search results page I navigate to the site actions menu and I select the edit page menu item
    image
  • I select the edit menu of the Search Core Results WebPart and the Modify Shared Web Part option
    image
  • In the Search Core Results –> Data View Properties –> I press XSL Editor..
    image
  • I replace all code with the following:
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform%22 >
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
    <xsl:template match="/">
    <xmp><xsl:copy-of select="*"/></xmp>
    </xsl:template>
    </xsl:stylesheet>
  • I press the apply Button

Notice the changes to the core results. A raw XML format of the results is displayed. But wait a minute… Where are the managed properties I created earlier? The answer is nowhere. I need to tell the WebPart to add those properties to the XML results:

  • In the Results Query Options of the Search Core Results properties, press the … icon in the Selected Columns option
    image
  • Notice the format and the changes I made to the bottom of the XML:
    <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance%22>
    <Columns>
    <Column Name="WorkId"/>
    <Column Name="Rank"/><Column Name="Title"/>
    <Column Name="Author"/>
    <Column Name="Size"/>
    <Column Name="Path"/>
    <Column Name="Description"/>
    <Column Name="Write"/><Column Name="SiteName"/>
    <Column Name="CollapsingStatus"/>
    <Column Name="HitHighlightedSummary"/>
    <Column Name="HitHighlightedProperties"/>
    <Column Name="ContentClass"/>
    <Column Name="IsDocument"/>
    <Column Name="PictureThumbnailURL"/>
    <Column Name="ProtOurPID"/>
    <Column Name="ProtSubject"/>
    <Column Name="ProtINOUT"/>
    <Column Name="ProtDocumentDate"/>
    <Column Name="ProtINTOriginDestination"/>
    <Column Name="ProtEXTOriginDestination"/>

    </Columns>
    </root>
  • Before the closing Columns statement </Columns> I added 6 of my managed properties in the form of: <Column Name=”MyManagedProperty” />
  • Press the OK Button

Now, I have my Raw XML results with my managed properties included. To manipulate their layout using Sharepoint Designer, I have to save those results as an XML file and import it as a data source:

  • I copy the raw XML format of the search results (from <All_Results> to </All_results>) into notepad and I save the file as RawXMLResults.xml somewhere in my local drive
  • I open my SharePoint site and I temporarily save the RawXMLResults.xml to one of my document libraries
  • In SharePoint Designer I create a new ASPX page
    image
  • In the Data View menu I select the Insert Data View Option…
    image
  • In the Data Source Library (Right Pane in SharePoint Designer) I expand the XML Files, and I select the Add an XML File… hyperlink:
    image
  • In the new window I select the Source tab and I browse for the RawXMLResults.xml file I saved in a previous step to one of my document libraries
  • After pressing OK the new XML file appears in the list of my XML Datasources
  • By selecting the file, a drop down menu appears. I click the Show Data Option
    image
  • Having selected the data source webpart in my ASPX Page
    image
  • I select the columns I want to add to my layout and from the Insert Selected Fields as… menu, I select the Multiple Item View
    image
  • Note that the order I selected the columns, is the order that is displayed in my table
  • After making the appropriate modifications to my layout, I need to copy the XSLT code and paste it back to my Search Core Results WebPart. So, I copy the code from the <xsl:stylesheet … to the </xsl:stylesheet> element.
    image
  • My final step is to paste the code to the XSL Editor… in my Search Core Results WebPart properties to see the effect.
    image

Personally I prefer to manipulate XSLT by using external file references instead of pasting the code directly to the WebPart. If you want to achieve the same, do the following:

  • Create a document library to host your XSL files (ex Transformations)
  • Instead of pasting the code from Sharepoint Designer directly to the WebPart, paste it to notepad and save the file as something.xsl
  • Upload something.xsl to your document library
  • In the XSL Editor… of the Search Core Results WebPart Reference to the file by using the sample code below:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform%22>

    <xsl:import href="/Transformations/something.xsl"/>

    <xsl:template match="/">
    <xsl:apply-imports/>
    </xsl:template>

    </xsl:stylesheet>

A last thing. In order to be able to sort results by relevance / by date and to display the predefined text in case there are no results to return back, you have to copy the following code from the shipped results XSLT to your custom one:

<xsl:param name="ResultsBy" />
<xsl:param name="ViewByUrl" />
<xsl:param name="ViewByValue" />
<xsl:param name="IsNoKeyword" />
<xsl:param name="IsFixedQuery" />
<xsl:param name="ShowActionLinks" />
<xsl:param name="MoreResultsText" />
<xsl:param name="MoreResultsLink" />
<xsl:param name="CollapsingStatusLink" />
<xsl:param name="CollapseDuplicatesText" />
<xsl:param name="AlertMeLink" />
<xsl:param name="AlertMeText" />
<xsl:param name="SrchRSSText" />
<xsl:param name="SrchRSSLink" />
<xsl:param name="ShowMessage" />
<xsl:param name="IsThisListScope" />
<xsl:param name="DisplayDiscoveredDefinition" select="True" />
<xsl:param name="NoFixedQuery" />
<xsl:param name="NoKeyword" />
<xsl:param name="NoResults" />
<xsl:param name="NoResults1" />
<xsl:param name="NoResults2" />
<xsl:param name="NoResults3" />
<xsl:param name="NoResults4" />
<xsl:param name="DefinitionIntro" />

<!-- When there is keywory to issue the search -->
<xsl:template name="dvt_1.noKeyword">
<span class="srch-description">
<xsl:choose>
<xsl:when test="$IsFixedQuery">
<xsl:value-of select="$NoFixedQuery" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$NoKeyword" />
</xsl:otherwise>
</xsl:choose>
</span>
</xsl:template>

<!-- When empty result set is returned from search -->
<xsl:template name="dvt_1.empty">
<div class="srch-sort">
<xsl:if test="$AlertMeLink and $ShowActionLinks">
<span class="srch-alertme" > <a href ="{$AlertMeLink}" id="CSR_AM1" title="{$AlertMeText}"><img style="vertical-align: middle;" src="/_layouts/images/bell.gif" alt="" border="0"/><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text><xsl:value-of select="$AlertMeText" /></a>
</span>
</xsl:if>

<xsl:if test="string-length($SrchRSSLink) &gt; 0 and $ShowActionLinks">
<xsl:if test="$AlertMeLink">

</xsl:if>
<a type="application/rss+xml" href ="{$SrchRSSLink}" title="{$SrchRSSText}" id="SRCHRSSL"><img style="vertical-align: middle;" border="0" src="/_layouts/images/rss.gif" alt=""/><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text><xsl:value-of select="$SrchRSSText"/></a>
</xsl:if>
</div>
<br/> <br/>

<span class="srch-description" id="CSR_NO_RESULTS">
<xsl:value-of select="$NoResults" />

<ol>
<li><xsl:value-of select="$NoResults1" /></li>
<li><xsl:value-of select="$NoResults2" /></li>
<li><xsl:value-of select="$NoResults3" /></li>
<li><xsl:value-of select="$NoResults4" /></li>
</ol>
</span>
</xsl:template>

<!-- Main body template. Sets the Results view (Relevance or date) options -->
<xsl:template name="dvt_1.body">
<div class="srch-results">
<xsl:if test="$ShowActionLinks">
<div class="srch-sort"> <xsl:value-of select="$ResultsBy" />
<xsl:if test="$ViewByUrl">

<a href ="{$ViewByUrl}" id="CSR_RV" title="{$ViewByValue}">
<xsl:value-of select="$ViewByValue" />
</a>
</xsl:if>
<xsl:if test="$AlertMeLink">

<span class="srch-alertme" > <a href ="{$AlertMeLink}" id="CSR_AM2" title="{$AlertMeText}"><img style="vertical-align: middle;" src="/_layouts/images/bell.gif" alt="" border="0"/><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text><xsl:value-of select="$AlertMeText" /></a>
</span>
</xsl:if>
<xsl:if test="string-length($SrchRSSLink) &gt; 0">

<a type="application/rss+xml" href ="{$SrchRSSLink}" title="{$SrchRSSText}" id="SRCHRSSL"><img style="vertical-align: middle;" border="0" src="/_layouts/images/rss.gif" alt=""/><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text><xsl:value-of select="$SrchRSSText"/></a>
</xsl:if>
</div>
<br /><br />
</xsl:if>
<xsl:apply-templates />

</div>
<xsl:call-template name="DisplayMoreResultsAnchor" />
</xsl:template>

<!—Your Results Template Goes Here –>

<!—Your Results Template Goes Here –>

<!-- The "view more results" for fixed query -->
<xsl:template name="DisplayMoreResultsAnchor">
<xsl:if test="$MoreResultsLink">
<a href="{$MoreResultsLink}" id="CSR_MRL">
<xsl:value-of select="$MoreResultsText"/>
</a>
</xsl:if>
</xsl:template>

<xsl:template match="All_Results/DiscoveredDefinitions">
<xsl:variable name="FoundIn" select="DDFoundIn" />
<xsl:variable name="DDSearchTerm" select="DDSearchTerm" />
<xsl:if test="$DisplayDiscoveredDefinition = 'True' and string-length($DDSearchTerm) &gt; 0">
<script language="javascript">
function ToggleDefinitionSelection()
{
var selection = document.getElementById("definitionSelection");
if (selection.style.display == "none")
{
selection.style.display = "inline";
}
else
{
selection.style.display = "none";
}
}
</script>
<div>
<a href="#" onclick="ToggleDefinitionSelection(); return false;">
<xsl:value-of select="$DefinitionIntro" /><b><xsl:value-of select="$DDSearchTerm"/></b></a>
<div id="definitionSelection" class="srch-Description" style="display:none;">
<xsl:for-each select="DDefinitions/DDefinition">
<br/>
<xsl:variable name="DDUrl" select="DDUrl" />
<xsl:value-of select="DDStart"/>
<b>
<xsl:value-of select="DDBold"/>
</b>
<xsl:value-of select="DDEnd"/>
<br/>
<xsl:value-of select="$FoundIn"/>
<a href="{$DDUrl}">
<xsl:value-of select="DDTitle"/>
</a>
</xsl:for-each>
</div>
</div>
</xsl:if>
</xsl:template>

<!-- XSL transformation starts here -->
<xsl:template match="/">
<xsl:if test="$AlertMeLink">
<input type="hidden" name="P_Query" />
<input type="hidden" name="P_LastNotificationTime" />
</xsl:if>
<xsl:choose>
<xsl:when test="$IsNoKeyword = 'True'" >
<xsl:call-template name="dvt_1.noKeyword" />
</xsl:when>
<xsl:when test="$ShowMessage = 'True'">
<xsl:call-template name="dvt_1.empty" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="dvt_1.body"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>