Custom Search Results

While customizing a SharePoint search results page, I received questions on how to generally customize search. In this post, I will show how to create a very simple standards-compliant search results page using customization only.

First of all, I create a custom search results page and add it to my site definition. I also ensure that the page is set to be the global search center target.

You need to activate the site collection feature "Office SharePoint Server Search Web Parts".

You can now add a web part named "Search Core Results" to your search results page. I configured this web part as:

  • Sentences In Summary = 5
  • Remove Duplicate Results = Check
  • Enable Search Term Stemming = Check
  • Show Messages = Clear
  • Show Search Results = Check
  • Show Action Links = Clear
  • Display "Relevance" View Option = Clear
  • Display "Modified Date" View Option = Clear
  • Display "Alert Me" Link = Clear
  • Display "RSS" Link = Clear

The output of the search results is controlled using XSL and the stylesheet is editable via the "XSL Editor..." option of the web part. Personally, I like to edit the XSL within Visual Studio 2008 to use debugging and all the other great XML/XSL editing features available here.

To do this, I save the original XSL into a file (transform.xsl) and change the XSL so that it will output the raw results data:

   1: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >


   2: <xsl:template match="/">


   3:     <xsl:copy-of select="node()" />


   4: </xsl:template>


   5: </xsl:stylesheet>




I then view the source of the page and save this XML into a file (in.xml).



I open the transform.xml file in Visual Studio, open the Properties window and select in.xml as the input. I create a file named out.xml for the output. Now, ensure you have the XML Editor toolbar open and click the "Show XSLT Output" or "Debug XSLT" button.



First, I move the template match="/" to the top so that the logic flow is represented correctly. In my example, I am not showing messages and do not allow alerts. Also, I am showing a very simple result mode, so I keep the node iteration within the main template instead of template matching on the "Result" node:





   1: <!-- Start of XSL transformation -->


   2: <xsl:template match="/">


   3:     <xsl:choose>


   4:       <xsl:when test="$IsNoKeyword = 'True'" >


   5:         <!-- Show "no keywords supplied" message -->


   6:         <xsl:call-template name="NoKeywords" />


   7:       </xsl:when>


   8:       <!-- Test if no data is found -->


   9:       <xsl:when test="$ShowMessage = 'True'">


  10:         <xsl:call-template name="NoResults" />


  11:       </xsl:when>      


  12:       <xsl:otherwise>


  13:         <div class="srch-results">


  14:           <xsl:for-each select="/All_Results/Result">


  15:             <a>


  16:               <xsl:attribute name="href">


  17:                 <xsl:value-of select="url"/>


  18:               </xsl:attribute>


  19:               <h3>


  20:                 <xsl:value-of select="title" />


  21:               </h3>


  22:             </a>


  23:             <p>


  24:               <xsl:call-template name="HitHighlighting">


  25:                 <xsl:with-param name="text" select="hithighlightedsummary" />


  26:               </xsl:call-template>


  27:             </p>


  28:           </xsl:for-each>


  29:         </div>


  30:       </xsl:otherwise>


  31:     </xsl:choose>    


  32: </xsl:template>




I then add the no keywords template (to follow logic flow order) and test it within the browser:





   1: <!-- Displayed when no keywords are submitted to the search -->


   2: <xsl:template name="NoKeywords">


   3:   <span class="srch-description srch-nokeyword">


   4:     Enter one or more words to search for in the search box.


   5:   </span>


   6: </xsl:template>




Then add the no search results template (to follow logic flow order) and test it within the browser:





   1: <!-- When empty result set is returned from search -->


   2: <xsl:template name="NoResults">


   3:   <span class="srch-description" id="CSR_NO_RESULTS">


   4:     <xsl:value-of select="$NoResults" />


   5:     <ol>


   6:       <li>


   7:         <xsl:value-of select="$NoResults1" />


   8:       </li>


   9:       <li>


  10:         <xsl:value-of select="$NoResults2" />


  11:       </li>


  12:       <li>


  13:         <xsl:value-of select="$NoResults3" />


  14:       </li>


  15:       <li>


  16:         <xsl:value-of select="$NoResults4" />


  17:       </li>


  18:     </ol>


  19:   </span>


  20: </xsl:template>




Finally, add the hit highlighting. Note that in the full file, I have template matches from c0 to c9 but have removed them here as it takes up too much space (and you get the idea):





   1: <!-- Highlights text by matching templates within the result text only -->


   2: <xsl:template name="HitHighlighting">


   3:   <xsl:param name="text" />


   4:   <xsl:apply-templates select="$text"/>


   5: </xsl:template>


   6:  


   7: <!-- Template for displaying spacers -->


   8: <xsl:template match="ddd">


   9:   <xsl:text> ... </xsl:text>


  10: </xsl:template>


  11:  


  12: <!-- Hit highlights for ten keywords passed. I kept this as we can then show, for example, different colours per keyword -->


  13: <xsl:template match="c0">    


  14:   <strong>


  15:     <xsl:value-of select="."/>


  16:   </strong>


  17: </xsl:template>


  18: <xsl:template match="c1">


  19:   <strong>


  20:     <xsl:value-of select="."/>


  21:   </strong>


  22: </xsl:template>


0 comments: