Umbraco网站制作(五) 搜索
一个网站肯定是少不了搜索的啦,虽然Umbraco自带有写好的这个组建下载就可以,但是只能对英文进行搜索。
中文会报错,经过两天研究,我改了一个出来,先说下怎么使用吧~!
前面具体步骤我不做多细致的讲解。
我们先找到Developer在Macros里面创建一个[XSLT]Search文件,名字必须得要这个,好象是保留的,用其他的还出不来!
再去创建XSLTSearch.xslt文件。代码如下,这个就是被我改过的。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
xmlns:ps="urn:percipientstudios-com:xslt"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<xsl:variable name="searchFields" select="ps:getListParameter(string(//macro/searchFields), 'bodyText')"/>
<xsl:variable name="previewFields" select="ps:getListParameter(string(//macro/previewFields), 'bodyText')"/>
<xsl:variable name="search">
<xsl:choose>
<xsl:when test="string(umbraco.library:RequestQueryString('search')) != ''">
<xsl:value-of select="ps:escapeSearchTerms(string(umbraco.library:RequestQueryString('search')))" />
</xsl:when>
<xsl:when test="string(umbraco.library:RequestForm('search')) != ''">
<xsl:value-of select="ps:escapeSearchTerms(string(umbraco.library:RequestForm('search')))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="''"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="unescapedSearch" select="ps:unescapeSearchTerms($search)"/>
<xsl:variable name="searchUpper" select="ps:uppercase(string($search))"/>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$search = ''">
<xsl:call-template name="search">
<xsl:with-param name="items" select="./node[1=2]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="search">
<xsl:with-param name="items" select="umbraco.library:GetXmlAll()"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="search">
<xsl:param name="items"/>
<xsl:variable name="possibleNodes" select="$items/descendant-or-self::node[
umbraco.library:IsProtected(@id, @path) = 0
and string(data [@alias='umbracoNaviHide']) != '1']"/>
<xsl:variable name="matchedNodesIdList">
<xsl:call-template name="booleanAndMatchedNodes">
<xsl:with-param name="yetPossibleNodes" select="$possibleNodes"/>
<xsl:with-param name="searchTermList" select="concat($searchUpper, ' ')"/>
</xsl:call-template>
</xsl:variable>
<!-- get the actual matching nodes as a nodeset -->
<xsl:variable name="matchedNodes" select="$possibleNodes[contains($matchedNodesIdList, concat(';', concat(@id, ';')))]" />
<div align="center">
<xsl:choose>
<xsl:when test="count($matchedNodes) = 0">
没有符合 <strong>
<xsl:value-of select="$unescapedSearch"/>
</strong> 的项
</xsl:when>
<xsl:otherwise>
项符合 <strong>
<xsl:value-of select="$unescapedSearch"/>
</strong> 的有 <strong>
<xsl:value-of select="count($matchedNodes)"/>
</strong> 项
</xsl:otherwise>
</xsl:choose>
</div>
<ul>
<xsl:for-each select="$matchedNodes">
<li>
<a href="{umbraco.library:NiceUrl(@id)}" class="xsltsearch_title">
<xsl:value-of select="data [@alias = 'PageHeader']"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template name="booleanAndMatchedNodes">
<xsl:param name="yetPossibleNodes"/>
<xsl:param name="searchTermList"/>
<xsl:variable name="searchTerm">
<xsl:value-of select="ps:getFirstElement($searchTermList, ' ')"/>
</xsl:variable>
<xsl:variable name="remainingSearchTermList">
<xsl:value-of select="ps:removeFirstElement($searchTermList, ' ')"/>
</xsl:variable>
<xsl:variable name="evenYetPossibleNodes" select="$yetPossibleNodes[attribute::*[(contains($searchFields,name())
and contains(ps:uppercase(umbraco.library:StripHtml(string(.))), $searchTerm)) ]]
|
$yetPossibleNodes[data[(contains($searchFields, concat(',',@alias,','))
and contains(ps:uppercase(umbraco.library:StripHtml(string(.))), $searchTerm)) ]]" />
<xsl:choose>
<xsl:when test="string-length($remainingSearchTermList) > 1">
<!-- continue to search the rest of the terms -->
<xsl:call-template name="booleanAndMatchedNodes">
<xsl:with-param name="yetPossibleNodes" select="$evenYetPossibleNodes"/>
<xsl:with-param name="searchTermList" select="$remainingSearchTermList"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- finished searching: return a list of the attribute @id's of the currently possible nodes as the final set of matched nodes -->
<xsl:variable name="nodeIDList">
<xsl:text>;</xsl:text>
<xsl:for-each select="$evenYetPossibleNodes">
<!-- @id for this node -->
<xsl:value-of select="@id"/>
<xsl:text>;</xsl:text>
</xsl:for-each>
</xsl:variable>
<!-- return the actual list of id's -->
<xsl:value-of select="$nodeIDList"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<msxsl:script language="C#" implements-prefix="ps">
<![CDATA[
public string uppercase(string s)
{
return s.ToUpper();
}
public string escapeSearchTerms(string data)
{
return data.Replace(Convert.ToString((char)38), "&");
}
public string unescapeSearchTerms(string data)
{
return data.Replace("&", Convert.ToString((char)38));
}
public string getFirstElement(string delimitedList, string delimiter)
{
// strip all leading delimiters
while (delimitedList.IndexOf(delimiter) == 0)
delimitedList = delimitedList.Remove(0, delimiter.Length).Trim();
if (delimitedList.Length == 0)
return "";
// searching on a phrase
if (delimiter == " " && delimitedList.Substring(0, 1) == "'" && delimitedList.IndexOf("'", 1) > -1)
return delimitedList.Substring(1, delimitedList.IndexOf("'", 1) - 1);
if (delimiter == " " && delimitedList.Substring(0, 1) == "\"" && delimitedList.IndexOf("\"", 1) > -1)
return delimitedList.Substring(1, delimitedList.IndexOf("\"", 1) - 1);
// only one element
if (delimitedList.IndexOf(delimiter) == -1)
return delimitedList.Trim();
// return first element
return delimitedList.Split(delimiter.ToCharArray()[0])[0].Trim();
}
public string removeFirstElement(string delimitedList, string delimiter)
{
string firstElement = getFirstElement(delimitedList, delimiter);
// handle phrase delimiters
if (delimiter == " " && delimitedList.Substring(0, 1) == "'" && delimitedList.IndexOf("'", 1) > -1)
return delimitedList.Remove(0, firstElement.Length + 2).Trim();
if (delimiter == " " && delimitedList.Substring(0, 1) == "\"" && delimitedList.IndexOf("\"", 1) > -1)
return delimitedList.Remove(0, firstElement.Length + 2).Trim();
while (delimitedList.IndexOf(delimiter) == 0)
delimitedList = delimitedList.Remove(0, delimiter.Length).Trim();
return delimitedList.Remove(0, firstElement.Length).Trim();
}
public string getListParameter(string value, string defaultValue)
{
/* Here is the XSLT way to do this, though it is slower and not as fault-tolerant as the C# function:
<xsl:variable name="previewFields">
<xsl:choose>
<!-- set default value -->
<xsl:when test="string(//macro/previewFields) = ''">,bodyText,description,</xsl:when>
<xsl:otherwise>
,<xsl:value-of select="string(//macro/previewFields)"/>,
</xsl:otherwise>
</xsl:choose>
</xsl:variable>-->
*/
// remove all spaces
value = value.Replace(" ", "");
defaultValue = defaultValue.Replace(" ", "");
if (value == "")
return "," + defaultValue + ",";
else
return "," + value + ",";
}
]]>
</msxsl:script>
</xsl:stylesheet>
然后在[XSLT]Search这个文件中有改动如下
指定xslt文件。然后Parameters里面设置如下参数
有点多,虽然这些参数在我xslt中没用到,被我改了,但是,少了也出不来,这个原因还在寻找。有知道也请交流下。
如果闲麻烦的朋友可以直接先下载一个他写好的搜索这块的代码,然后把我的xslt文件代码粘进去也可以,具体如何去下载,我会在下一篇文章中讲解。
接着,我们在Document Type中添加一个Seache Page的文件类型。
具体步骤像前几篇说到的。最后我们编辑模板。
<?UMBRACO_MACRO macroAlias="XSLTSearch" source="-1" searchFields="@nodeName,PageTitle,secondaryTitle,bodyText" previewFields="bodyText,secondaryTitle,PageTitle" searchBoxLocation="TOP" previewType="CONTEXT" resultsPerPage="5" previewChars="100" showPageRange="1" showOrdinals="1" showScores="0" showStats="1"></?UMBRACO_MACRO>
这是Seache Page模板中的内容,就是掉用搜索的xslt,参数那么多,就是因为上面我们定义的~!
注意选择:Master template 这样一个搜索页面就OK啦~!
接下来比如我们想要在主模板的一个div里面把我们的搜索放上,该如何做呢?
我们找到主模板在需要搜索的地方放上如下代码:
<!-- 搜索 -->
<form method="post" action="/Search.aspx">
<input type="text" name="search" /><input type="submit" name="submit" value="" class="Submit" style="border-style: none; background-image: url('../data/images/Seach.jpg'); background-repeat: no-repeat; width: 23px;"/>
</form>
就是一个表单,这个表单也是同样提交给我的Seach页面效果如图:
这个时候搜索就完啦~!效果请看
符合的内容都出来了~!说明下,这里的搜索不当搜索标题,而且也会搜索内容。但是在数据特别多的时候就显的力不从心啦,
因为Umbraco的数据读取都是从数据到XML的,而搜索是读取整个XML文件,当内容特别多的时候,就会比较慢啦~!但是对于小网站
门户网站组够用了,而且效果都还不错~!
希望能给大家帮助,如果有更好的方法还请多多交流。