Every time i've been using MOSS 2007 search, i always wanted to have a
very simple thing. Before going deeper into the explanations, let's
look to the typical item returned after doing the search.
What we see here?
Actually we see almost everything that MOSS 2007 search could return OOB (out of the box).
If you are interested for the details, see Microsoft.Search Schema Reference for Enterprise Search. Also it is worth to check the article Creating and Exposing Managed Properties in the Advanced Search Page of SharePoint Server Enterprise Search.
But what is the problem?
The problem is that very often it is nice not only to click on the
URL and get the item opened in the corresponding desktop application,
but also be able to navigate to the place, where this item is stored.
For example, you've been so impressed by my presentation about Groove
that you've decided to go to the document library where it is stored and
check for something more.. :)
Again, OOB you would have to:
- click on the link
- copy the url to the document
- paster it to the IE address bar
- manually delete document name and leave only the path to the document library
Not so easy, yes?
Thanks to our MS developers you have an ability to change this.
In order to do this you have to modify the XSLT rendering script used for search results output.
The form in which MOSS outputs the results to XML is the following:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="url-strip-final.xslt"?>
<All_Results>
<Result>
<workid>1</workid>
<rank>222</rank>
<title>Title of document or web page</title>
<author>Author of document or web page</author>
<size>1025</size>
<sitename>http://www.sample.com</sitename>
<url>http://www.sample.com/folder/document.aspx</url>
<imageurl>/_layouts/images/aspx16.gif</imageurl>
<description>This
is the summary of the document or web page. The summary is generated
from the original document based on matches with query terms. In some
cases, the summary is a description provided by the
author.</description>
<write>December 26, 2004</write>
</Result>
<Result>
<workid>1</workid>
<rank>222</rank>
<title>Title of document or web page</title>
<author>Author of document or web page</author>
<size>1025</size>
<sitename>http://www.sample.com</sitename>
<url>http://www.sample.com</url>
<imageurl>/_layouts/images/aspx16.gif</imageurl>
<description>This
is the summary of the document or web page. The summary is generated
from the original document based on matches with query terms. In some
cases, the summary is a description provided by the
author.</description>
<write>December 26, 2004</write>
</Result>
<Result>
<workid>1</workid>
<rank>222</rank>
<title>Title of document or web page</title>
<author>Author of document or web page</author>
<size>1025</size>
<sitename>http://www.sample.com</sitename>
<url>http://www.sample.com/sites/test</url>
<imageurl>/_layouts/images/aspx16.gif</imageurl>
<description>This
is the summary of the document or web page. The summary is generated
from the original document based on matches with query terms. In some
cases, the summary is a description provided by the
author.</description>
<write>December 26, 2004</write>
</Result>
<Result>
<workid>1</workid>
<rank>222</rank>
<title>Title of document or web page</title>
<author>Author of document or web page</author>
<size>1025</size>
<sitename>http://www.sample.com</sitename>
<url>http://test/Docs/pics/Forms/DispForm.aspx?ID=2&RootFolder=/Docs/pics</url>
<imageurl>/_layouts/images/aspx16.gif</imageurl>
<description>This
is the summary of the document or web page. The summary is generated
from the original document based on matches with query terms. In some
cases, the summary is a description provided by the
author.</description>
<write>December 26, 2004</write>
</Result></All_Results>
You can get nearly the same XML from Search Results web-part
toolpane. The thing that i've added here is some special conditions
which has to be handled.
The first one is the situation, when you
receive in the results link to the site, which is the root for site
collection. In the XML decribed above it is http://www.sample.com/sites/test.
If we would like to get to it's parent, it would be http://www.sample.com/ and not http://www.sample.com/sites.
Anyway, to stay with XSLT and not use anything else, you could write the following type of XSLT script to get the desired result.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<!-- mail processing template, is applied to the each resulting item -->
<xsl:template match="Result">
<!-- getting the url to the item, returned from search -->
<xsl:variable name="result-url" select="url"/>
<xsl:variable name="res1">
<xsl:choose>
<!--for now i have now idea how to deal with urls with ? chars, so we would skip them -->
<xsl:when test="contains( $result-url, '?' )">
<xsl:value-of select="$result-url"/>
</xsl:when>
<!--for urls that are not referring the root of the web applications, we perform the processing -->
<xsl:when test="contains( substring-after( $result-url,'http://') ,'/')">
<xsl:call-template name="mcs-strip-filename">
<xsl:with-param name="x" select="$result-url"/>
</xsl:call-template>
</xsl:when>
<!-- for all other conditions we do nothing -->
<xsl:otherwise>
<xsl:value-of select="$result-url"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- postprocessing-->
<xsl:variable name="res2">
<xsl:choose>
<!-- if search returned is the item like http://test we would leave it untouched -->
<xsl:when test="$result-url=$res1">
<xsl:value-of select="$res1"/>
</xsl:when>
<!-- if search returned us the result like http://test/sites/site, than the parent should be http://test and not http://test/sites -->
<xsl:when test="substring-after($result-url,'sites/')=$res1">
<xsl:value-of select="substring-before($result-url,concat('/sites/',$res1))"/>
</xsl:when>
<!-- in all other situations we just strip the doc name from the end and return the result -->
<xsl:otherwise>
<xsl:value-of select="substring-before($result-url,$res1)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
original-url=<xsl:value-of select="$result-url"/><br/>
<a href="{$res1}">doc-<xsl:value-of select="$res1"/></a><br/>
<a href="{$res2}">parent-<xsl:value-of select="$res2"/></a><br/>
<br/>
</xsl:template>
<xsl:template name="mcs-strip-filename">
<xsl:param name="x"/>
<xsl:choose>
<xsl:when test="contains($x,'/')">
<xsl:call-template name="mcs-strip-filename">
<xsl:with-param name="x" select="substring-after($x,'/')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$x"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
(note* - it was more than 2 years ago when i've did something using
XSLT, so excuse me if you think it could be writtent better or has
some errors).
This XSLT does few simple things and the main one is that it gives you an ability to get the link to the container for the item.
.xml and .xslt files described above have been made to demonstrate the possiblity to achieve the results.
Now let's try to make MOSS 2007 use this. To do this you should open the XSLT editor for Search Results web-part and edit the OOB XSLT. To make it simple search for the string that looks like
<xsl:call-template name="DisplaySize">
<xsl:with-param name="size" select="size" />
</xsl:call-template>
and add just before it the following strings:
<xsl:call-template name="mcs-get-parent">
<xsl:with-param name="result-url" select="url" />
</xsl:call-template>
After that go to the end of xslt and just before the </xsl:stylesheet> node add the following code
<xsl:template name="mcs-get-parent">
<!-- getting the url to the item, returned from search -->
<xsl:param name="result-url"/>
<xsl:variable name="res1">
<xsl:choose>
<!--for now i have now idea how to deal with urls with ? chars, so we would skip them -->
<xsl:when test="contains( $result-url, '?' )">
<xsl:value-of select="$result-url"/>
</xsl:when>
<!--for urls that are not referring the root of the web applications, we perform the processing -->
<xsl:when test="contains( substring-after( $result-url,'http://') ,'/')">
<xsl:call-template name="mcs-strip-filename">
<xsl:with-param name="x" select="$result-url"/>
</xsl:call-template>
</xsl:when>
<!-- for all other conditions we do nothing -->
<xsl:otherwise>
<xsl:value-of select="$result-url"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- postprocessing-->
<xsl:variable name="res2">
<xsl:choose>
<!-- if search returned is the item like http://test we would leave it untouched -->
<xsl:when test="$result-url=$res1">
<xsl:value-of select="$res1"/>
</xsl:when>
<!-- if search returned us the result like http://test/sites/site, than the parent should be http://test and not http://test/sites -->
<xsl:when test="substring-after($result-url,'sites/')=$res1">
<xsl:value-of select="substring-before($result-url,concat('/sites/',$res1))"/>
</xsl:when>
<!-- in all other situations we just strip the doc name from the end and return the result -->
<xsl:otherwise>
<xsl:value-of select="substring-before($result-url,$res1)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<span
class="srch-URL"><xsl:text
disable-output-escaping="yes">&nbsp;</xsl:text><a
href="{$res2}">navigate to parent</a></span>
</xsl:template>
<xsl:template name="mcs-strip-filename">
<xsl:param name="x"/>
<xsl:choose>
<xsl:when test="contains($x,'/')">
<xsl:call-template name="mcs-strip-filename">
<xsl:with-param name="x" select="substring-after($x,'/')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$x"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
After applying the changes you would be able to see those type of changes in the result:
I hope it would be usefull for you and help to get the maximum from MOSS 2007.
原文地址:http://blogs.technet.com/b/pavelka/archive/2007/05/24/moss-2007-search-customization.aspx