zoukankan      html  css  js  c++  java
  • 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) &gt; 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), "&amp;");
        }

        public string unescapeSearchTerms(string data)
        {
            return data.Replace("&amp;", 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; 23px;"/>
      </form>
    就是一个表单,这个表单也是同样提交给我的Seach页面效果如图:

    这个时候搜索就完啦~!效果请看

    符合的内容都出来了~!说明下,这里的搜索不当搜索标题,而且也会搜索内容。但是在数据特别多的时候就显的力不从心啦,

    因为Umbraco的数据读取都是从数据到XML的,而搜索是读取整个XML文件,当内容特别多的时候,就会比较慢啦~!但是对于小网站

    门户网站组够用了,而且效果都还不错~!

    希望能给大家帮助,如果有更好的方法还请多多交流。

  • 相关阅读:
    C#递规与分治策略
    SuperMap Objects Java & Applet
    如何提高显示速度
    系统测试
    ora01033:oracle initialization or shutdown in progress
    ORA12535: TNS:operation timed out。
    oralce01033
    hsql初体验
    创建Oracle数据源失败
    转载地图优化
  • 原文地址:https://www.cnblogs.com/liluping860122/p/1251325.html
Copyright © 2011-2022 走看看