Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • William Schwartz 16 posts 85 karma points
    Feb 16, 2011 @ 23:22
    William Schwartz
    0

    Error reading XSLT file: \xslt\XSLTsearch.xslt

    Hi Doug-- 

    Great search. However, under very specific conditions (using Umbraco 4.5.2 and XSLTsearch 3.0.) I receive this error:

    "Error parsing XSLT file: \xslt\XSLTsearch.xslt"

    The conditions are:

    1. When the search term is present in the nodeName and
    2. When a Macro is added through a Rich Text Editor (without any other content) to a child node of the Page node
    For example:
    Search term: planning
    The published "umbraco.config" file contains:
            <Page id="1075" parentID="1068" level="4" writerID="0" creatorID="0" nodeType="1056" template="1057" sortOrder="3" createDate="2011-01-11T13:27:23" updateDate="2011-02-16T16:44:25" nodeName="Planning Commission" urlName="planning-commission" writerName="Administrator" creatorName="Administrator" path="-1,1161,1059,1068,1075" isDoc="">
              <page_heading />
              <menu_text />
              <page_content><![CDATA[
    <?UMBRACO_MACRO board="pc" macroAlias="Boards"
    />
    ]]></page_content>
    Using the umbDebugShowTrace=true I see the following two errors:
    umbracoMacro InnerException
    An error occurred during a call to extension function 'escapingIntelligentSubstring'. See InnerException for a complete description of the error.
    An error occurred during a call to extension function 'escapingIntelligentSubstring'. See InnerException for a complete description of the error.
      at System.Xml.Xsl.Runtime.XmlExtensionFunction.Invoke(Object extObj, Object[] args)
      at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args)
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:template name="search">(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current, Double {urn:schemas-microsoft-com:xslt-debug}position, Double {urn:schemas-microsoft-com:xslt-debug}last, IList`1 {urn:schemas-microsoft-com:xslt-debug}namespaces, IList`1 items) in D:\Websites\active\uppersouthampton-umbraco\xslt\XSLTsearch.xslt:line 381
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:template match="/">(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current, Double {urn:schemas-microsoft-com:xslt-debug}position, Double {urn:schemas-microsoft-com:xslt-debug}last, IList`1 {urn:schemas-microsoft-com:xslt-debug}namespaces) in D:\Websites\active\uppersouthampton-umbraco\xslt\XSLTsearch.xslt:line 125
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:apply-templates>(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator , Double , Double )
      at System.Xml.Xsl.CompiledQuery.Query.Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
      at System.Xml.Xsl.CompiledQuery.Query.Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
      at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
      at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, Boolean closeWriter)
      at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results)
      at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results)
      at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results)
      at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters)
      at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt)
      at umbraco.macro.loadMacroXSLT(macro macro, Hashtable attributes, Hashtable pageElements)
    umbracoMacro InnerException
    Index and length must refer to a location within the string.
    Parameter name: length
    Index and length must refer to a location within the string.
    Parameter name: length
      at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy)
      at PS.XSLTsearch.escapingIntelligentSubstring(String data, Int32 unescapedStart, Int32 unescapedLength
    If I republish the page with additional content either before or after the Macro the search works as expected.
    The updated .config after the change:
            <Page id="1075" parentID="1068" level="4" writerID="0" creatorID="0" nodeType="1056" template="1057" sortOrder="3" createDate="2011-01-11T13:27:23" updateDate="2011-02-16T16:44:25" nodeName="PlanningCommission" urlName="planning-commission" writerName="Administrator" creatorName="Administrator" path="-1,1161,1059,1068,1075" isDoc="">
              <page_heading />
              <menu_text />
              <page_content><![CDATA[
    <p>More text</p>

    <?UMBRACO_MACRO board="pc" macroAlias="Boards" />
    ]]></page_content>
    We looked at the XSLTserach.cs file where the "escapingIntelligentSubstring" function resides but it's not overly apparent to us where the problem maybe. If you have any thoughts about this it would be a great help.
    Thanks for your assistance, and thanks again for a wonderful search solution.
    -Wm
  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Feb 18, 2011 @ 08:35
    Douglas Robar
    0

    Thanks for the excellent bug report! I'll look into it an let you know what I find out. Hopefully a quick and simple solution.

    cheers,
    doug.

  • William Schwartz 16 posts 85 karma points
    Feb 21, 2011 @ 17:48
    William Schwartz
    0

    Thanks Doug. Let me know if I can be of more assistance.

    -Wm

  • William Schwartz 16 posts 85 karma points
    Mar 07, 2011 @ 21:51
    William Schwartz
    0

    Doug,

    Just wanted to check in to see if you had found anything.

    Thanks,

    -Wm

  • Ben McKean 272 posts 549 karma points
    Mar 08, 2011 @ 17:29
    Ben McKean
    0

    I had the same error but managed to get it working with a quick change to the XSLT.

    On line 758 I changed the choose/when statement to if statement (as recommended here http://our.umbraco.org/projects/website-utilities/xsltsearch/xsltsearch-bugs/13035-context-unavailable-bug-plus-fix-%28only-showing-1-preview-field%29).

    So it went from:

        <xsl:choose>
          <!-- actually print out field, if it exists and has content -->
          <xsl:when test="count($item/*[not(@isDoc) and name()=string($fieldName)]) = 1 and string($item/*[not(@isDoc) and name()=string($fieldName)]) != ''">
            <xsl:value-of select="string($item/*[not(@isDoc) and name()=string($fieldName)])"/>
          </xsl:when>

          <xsl:when test="$remainingFields != ''">
            <!-- if this element does not exist, go on to the next one -->
            <xsl:call-template name="displayFieldText">
              <xsl:with-param name="item" select="$item"/>
              <xsl:with-param name="fieldList" select="$remainingFields"/>
            </xsl:call-template>
          </xsl:when>
        </xsl:choose>

     

    To:

        <!--<xsl:choose>-->
          <!-- actually print out field, if it exists and has content -->
          <xsl:if test="count($item/*[not(@isDoc) and name()=string($fieldName)]) = 1 and string($item/*[not(@isDoc) and name()=string($fieldName)]) != ''">
            <xsl:value-of select="string($item/*[not(@isDoc) and name()=string($fieldName)])"/>
          </xsl:if>

          <xsl:if test="$remainingFields != ''">
            <!-- if this element does not exist, go on to the next one -->
            <xsl:call-template name="displayFieldText">
              <xsl:with-param name="item" select="$item"/>
              <xsl:with-param name="fieldList" select="$remainingFields"/>
            </xsl:call-template>
          </xsl:if>
        <!--</xsl:choose>-->

    Hope that works for you, seems to have done the trick for me.

    Ben

  • Djan Blom 99 posts 161 karma points
    Mar 08, 2011 @ 18:29
    Djan Blom
    0

    Hi, I followed the thread on the sideline - i have the same problem.

    But now i get this error :

    Error in XSLT at line 760, char 13
    758:       <xsl:choose>
    759:       <!-- actually print out field, if it exists and has content -->
    760: >>>   <xsl:if
    test="count($item/*[not(@isDoc) and name()=string($fieldName)]) = 1 and
    string($item/*[not(@isDoc) and name()=string($fieldName)]) != ''">
    <<<

    761:       <xsl:value-of select="string($item/*[not(@isDoc) and name()=string($fieldName)])"/>
    762:       </xsl:if>

    The solution is running here :

    http://djan.v5.baseshop.dk/

  • Djan Blom 99 posts 161 karma points
    Mar 08, 2011 @ 18:51
    Djan Blom
    0

    I changed <xsl:choose> to <xsl:if>'s, and got the following :

     

    System.Xml.Xsl.XslLoadException: Missing mandatory attribute 'test'. An 
    error occurred at
    \\Umbraco4.6.2\Djan\build\xslt\634352068837286615_temp.xslt(758,6).


    at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)


    at umbraco.presentation.webservices.codeEditorSave.SaveXslt(String
    fileName, String oldName, String fileContents, Boolean ignoreDebugging)

    It would be really great if someone could come up with a solution for this..

  • Jan Skovgaard 11280 posts 23678 karma points MVP 10x admin c-trib
    Mar 08, 2011 @ 21:29
    Jan Skovgaard
    0

    Hi Djan

    What exactly does your code look like now?

    You can't create an <xsl:if> without the test attribute.

    In the code you have posted above you have uncommented the choose, which was commented out in the example provided by Ben. (His second one).

    When you make a choose the construction needs to be

    <xsl:choose>

    <xsl:when test="testcondition">Value when test is matched</xsl:when>

    <xsl:otherwise>Value if test is not matched</xsl:otherwise>

    </xsl:choose>

    You can have as many <xsl:when test="something"></xsl:when> as you like, but once one of the tests return true the rest is not being tested so you should always think such a test scenario through.

    I hope this makes sense to you.

    /Jan

  • William Schwartz 16 posts 85 karma points
    Mar 08, 2011 @ 22:13
    William Schwartz
    0

    Ben,

    Thanks for suggestion, unfortunately my problem still persists.

    I think my issue may be in the .cs file.

    Thanks again.

    -Wm

  • Djan Blom 99 posts 161 karma points
    Mar 09, 2011 @ 09:16
    Djan Blom
    0

    Hi Jan,

    Sorry for this huge post ;x

    I see errors in line 437 and 443, the </input>-tags turn red..

    Other than that, I dont know whats causing it..

    - har du en msn? :)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE xsl:stylesheet [
      <!ENTITY nbsp "&#x00A0;">
    ]>
    <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.XSLTsearch="urn:PS.XSLTsearch"
      exclude-result-prefixes="msxml umbraco.library PS.XSLTsearch">

      <xsl:output method="xml" omit-xml-declaration="yes" />

      <!--
      ======================================================================
      XSLTsearch.xslt
      ======================================================================
      Copyright 2006-2010 Percipient Studios. All rights reserved.
      MIT License (http://www.opensource.org/licenses/mit-license.php)

      Version 3.0 - For umbraco 4.5+ and new XML schema
                    Adds multi-lingual dictionary support (defaults to EN-US)
                    Adds medium trust support (C# helper functions now in /app_code/XSLTsearch.cs)
                    Numerous bug fixes
      
      www.percipientstudios.com
      ======================================================================
      -->

      <xsl:param name="currentPage"/>

      <xsl:variable name="startTime" select="PS.XSLTsearch:getTime()"/>
      <xsl:variable name="currentID" select="$currentPage/@id"/>
      <xsl:variable name="XSLTsearchVersion" select="'3.0'"/>

      <!--
    DICTIONARY parameters for localization. Use default (English) text if
    dictionary item does not exist or has no value -->

      <xsl:variable name="dictionaryButton-Search" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Button-Search')), 'Search')"/>
      <xsl:variable name="dictionaryDescription-Context" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Description-Context')), 'Context')"/>
      <xsl:variable name="dictionaryDescription-ContextUnavailable" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Description-ContextUnavailable')),
    'unavailable')"
    />
      <xsl:variable name="dictionaryHeading-SearchResults" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Heading-SearchResults')),
    'Search Results')"
    />
      <xsl:variable name="dictionaryNavigation-Next" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Navigation-Next')), 'Next')"/>
      <xsl:variable name="dictionaryNavigation-Previous" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Navigation-Previous')), 'Previous')"/>
      <xsl:variable name="dictionaryPageRange-ShowingResults" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]PageRange-ShowingResults')),
    'Showing results')"
    />
      <xsl:variable name="dictionaryPageRange-To" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]PageRange-To')), 'to')"/>
      <xsl:variable name="dictionaryScore-Score" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Score-Score')), 'score')"/>
      <xsl:variable name="dictionaryStats-PagesIn" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Stats-PagesIn')), 'pages in')"/>
      <xsl:variable name="dictionaryStats-Searched" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Stats-Searched')), 'Searched')"/>
      <xsl:variable name="dictionaryStats-Seconds" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Stats-Seconds')), 'seconds')"/>
      <xsl:variable name="dictionarySummary-Matches" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Summary-Matches')), 'matches')"/>
      <xsl:variable name="dictionarySummary-NoMatchesWereFoundFor" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Summary-NoMatchesWereFoundFor')),
    'No matches were found for')"
    />
      <xsl:variable name="dictionarySummary-Page" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Summary-Page')), 'page')"/>
      <xsl:variable name="dictionarySummary-Pages" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Summary-Pages')), 'pages')"/>
      <xsl:variable name="dictionarySummary-YourSearchFor" select="PS.XSLTsearch:getDictionaryParameter(string(umbraco.library:GetDictionaryItem('[XSLTsearch]Summary-YourSearchFor')),
    'Your search for')"
    />

      <!-- MACRO parameters get default values if not passed in from the macro -->
      <xsl:variable name="source" select="string(PS.XSLTsearch:getParameter(string(/macro/source), '-1'))"/>
      <xsl:variable name="resultsPerPage" select="string(PS.XSLTsearch:getParameter(string(/macro/resultsPerPage), '5'))"/>
      <xsl:variable name="previewChars" select="string(PS.XSLTsearch:getParameter(string(/macro/previewChars), '255'))"/>
      <xsl:variable name="searchBoxLocation" select="PS.XSLTsearch:uppercase(PS.XSLTsearch:getParameter(string(/macro/searchBoxLocation), 'bottom'))"/>
      <!-- valid choices are: 'bottom' or 'top' or 'both' or 'none' -->
      <xsl:variable name="previewType" select="PS.XSLTsearch:uppercase(PS.XSLTsearch:getParameter(string(/macro/previewType), 'beginning'))"/>
      <!-- valid choices are: 'beginning' and 'context' -->
      <xsl:variable name="showPageRange" select="PS.XSLTsearch:uppercase(PS.XSLTsearch:getParameter(string(/macro/showPageRange), '0'))"/>
      <xsl:variable name="showOrdinals" select="PS.XSLTsearch:uppercase(PS.XSLTsearch:getParameter(string(/macro/showOrdinals), '0'))"/>
      <xsl:variable name="showScores" select="PS.XSLTsearch:uppercase(PS.XSLTsearch:getParameter(string(/macro/showScores), '0'))"/>
      <xsl:variable name="showStats" select="PS.XSLTsearch:uppercase(PS.XSLTsearch:getParameter(string(/macro/showStats), '0'))"/>
      <xsl:variable name="showDebug" select="PS.XSLTsearch:uppercase(PS.XSLTsearch:getParameter(string(umbraco.library:RequestQueryString('umbDebugShowTrace')), '0'))"/>

      <!-- which umbraco fields to search -->
      <!-- Note: Comma-separated list of fields. The order of the search fields affects the search score and
        order of the search results! Place the more important fields first, with bodyText last.
        The reason is that if a search term appears in the page's title, there is a greater likelihood
        that page discusses the search term at length, than it simply being mentioned in the bodyText in passing.
      -->
      <xsl:variable name="searchFields" select="PS.XSLTsearch:getListParameter(string(/macro/searchFields), '@nodeName,metaKeywords,metaDescription,bodyText')"/>

      <!-- which umbraco field to display for a found entry -->
      <!-- Note: Comma-separated list of fields. The order of the preview fields is from most preferred
        to least preferred. Put the most appropriate fields first (typically, bodyText).
        Note: ONLY works for properties, not attributes  
      -->
      <xsl:variable name="previewFields" select="PS.XSLTsearch:getListParameter(string(/macro/previewFields), 'bodyText,metaDescription')"/>

      <!-- the search term to look for -->
      <xsl:variable name="search">
        <xsl:choose>
          <!-- form field value, if present -->
          <xsl:when test="string(umbraco.library:RequestForm('search')) != ''">
            <xsl:value-of select="PS.XSLTsearch:escapeString(string(umbraco.library:RequestForm('search')))" />
          </xsl:when>
          <!-- querystring value, if present -->
          <xsl:when test="string(umbraco.library:RequestQueryString('search')) != ''">
            <xsl:value-of select="PS.XSLTsearch:escapeString(string(umbraco.library:RequestQueryString('search')))" />
          </xsl:when>
          <!-- no value -->
          <xsl:otherwise>
            <xsl:value-of select="''"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:variable name="unescapedSearch" select="PS.XSLTsearch:unescapeString($search)"/>

      <!-- We have to calculate matching nodes before we can finish calculating the rest of the variables/parameters... -->
      <!-- uppercase the search string for case-insensitive searching -->
      <xsl:variable name="searchUpper" select="PS.XSLTsearch:uppercase(string($search))"/>


      <!-- ============================================================= -->


      <xsl:template match="/">
        <!-- determine which nodeset to search through, based on the value (or absence) of the SOURCE parameter in the macro -->
        <xsl:choose>
          <!-- short-circuit the whole searching if no search-text were passed in -->
          <xsl:when test="$search = ''">
            <!-- using NO nodes; only calling the template for the form -->
            <xsl:call-template name="search">
              <xsl:with-param name="items" select="./node[1=2]"/>
            </xsl:call-template>
          </xsl:when>

          <xsl:when test="number($source)= -1 or number($source)= 0">
            <!-- using ALL nodes -->
            <xsl:call-template name="search">
              <xsl:with-param name="items" select="umbraco.library:GetXmlAll()/*"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="number($source)=$currentID">
            <!-- using only nodes within the search page's family tree, from top to bottom -->
            <xsl:call-template name="search">
              <xsl:with-param name="items" select="$currentPage/ancestor-or-self::* [@isDoc and @level = 1]"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <!-- search only within the SOURCE node specified in the macro and all of its children -->
            <xsl:call-template name="search">
              <xsl:with-param name="items" select="./descendant-or-self::*[@isDoc]"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="search">
        <!-- Perform the search on the appropriate nodeset and display the output -->
        <xsl:param name="items"/>

        <!-- reduce the number of nodes for applying all the functions in the next step -->
        <xsl:variable name="possibleNodes" select="$items/descendant-or-self::*[
                                 @isDoc
                                 and string(umbracoNaviHide) != '1'
                                 and count(attribute::id)=1
                                 and (umbraco.library:IsProtected(@id, @path) = false()
                                  or umbraco.library:HasAccess(@id, @path) = true())
                               ]"/>

        <!-- generate a string of a semicolon-delimited list of all @id's of the matching nodes -->
        <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, ';')))]" />

        <!-- the current page -->
        <xsl:variable name="page">
          <xsl:choose>
            <!-- first page -->
            <xsl:when test="number(umbraco.library:RequestQueryString('page')) &lt;=1
                or string(umbraco.library:RequestQueryString('page')) = ''
                or string(number(umbraco.library:RequestQueryString('page'))) = 'NaN'
                or (
                  string(umbraco.library:RequestForm('search')) != ''
                  and string(umbraco.library:RequestForm('search')) != string(umbraco.library:RequestQueryString('search'))
                )
            ">
              <xsl:text>1</xsl:text>
            </xsl:when>
            <!-- last page -->
            <xsl:when test="number(umbraco.library:RequestQueryString('page')) &gt; count($matchedNodes) div $resultsPerPage">
              <xsl:value-of select="ceiling(count($matchedNodes) div $resultsPerPage)"/>
            </xsl:when>
            <!-- the value specified in the querystring -->
            <xsl:otherwise>
              <xsl:value-of select="number(umbraco.library:RequestQueryString('page'))"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <!-- calculate a few handy variables now, for easy access later -->
        <xsl:variable name="startMatch" select="($page - 1) * $resultsPerPage + 1"/>
        <xsl:variable name="endMatch">
          <xsl:choose>
            <!-- all the rest (on the last page) -->
            <xsl:when test="($page * $resultsPerPage) &gt; count($matchedNodes)">
              <xsl:value-of select="count($matchedNodes)"/>
            </xsl:when>
            <!-- only the appropriate number for this page -->
            <xsl:otherwise>
              <xsl:value-of select="$page * $resultsPerPage"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <!-- display results header information to the screen, if a search has been run; otherwise just show the search form -->
        <div id="xsltsearch">
          <xsl:if test="$unescapedSearch !=''">
            <!--
    most pages have a search header specified in the template. If you wish
    XSLTsearch to display its own header, uncomment the <h2> ...
    </h2> lines below -->

            <!--
            <h2>
              <xsl:value-of select="$dictionaryHeading-SearchResults"/>
            </h2>
            -->

            <!-- display search box at the top of the page (the search box is always present even if no search was attempted) -->
            <xsl:if test="$searchBoxLocation='TOP' or $searchBoxLocation='BOTH'">
              <div class="xsltsearch_form">
                <input name="search" type="text" class="input">
                  <xsl:attribute name="value">
                    <xsl:value-of select="$unescapedSearch"/>
                  </xsl:attribute>
                </input>
                <xsl:text>&nbsp;</xsl:text>
                <input type="submit" class="submit">
                  <xsl:attribute name="value">
                    <xsl:value-of select="$dictionaryButton-Search"/>
                  </xsl:attribute>
                </input>
              </div>
            </xsl:if>

            <p id="xsltsearch_summary">
              <xsl:choose>
                <xsl:when test="count($matchedNodes) = 0">
                  <xsl:value-of select="$dictionarySummary-NoMatchesWereFoundFor"/>
                  <xsl:text> </xsl:text>
                  <strong>
                    <xsl:value-of select="$unescapedSearch"/>
                  </strong>
                </xsl:when>
                <xsl:when test="count($matchedNodes) = 1">
                  <xsl:value-of select="$dictionarySummary-YourSearchFor"/>
                  <xsl:text> </xsl:text>
                  <strong>
                    <xsl:value-of select="$unescapedSearch"/>
                  </strong>
                  <xsl:text> </xsl:text>
                  <xsl:value-of select="$dictionarySummary-Matches"/>
                  <xsl:text> </xsl:text>
                  <strong>1</strong>
                  <xsl:text> </xsl:text>
                  <xsl:value-of select="$dictionarySummary-Page"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$dictionarySummary-YourSearchFor"/>
                  <xsl:text> </xsl:text>
                  <strong>
                    <xsl:value-of select="$unescapedSearch"/>
                  </strong>
                  <xsl:text> </xsl:text>
                  <xsl:value-of select="$dictionarySummary-Matches"/>
                  <xsl:text> </xsl:text>
                  <strong>
                    <xsl:value-of select="count($matchedNodes)"/>
                  </strong>
                  <xsl:text> </xsl:text>
                  <xsl:value-of select="$dictionarySummary-Pages"/>
                </xsl:otherwise>
              </xsl:choose>

              <!-- show the page number range. Useful if you don't show the ordinal for the result -->
              <xsl:if test="$showPageRange != '0'">
                <xsl:if test="count($matchedNodes) &gt; 0">
                  <br />
                  <span id="xsltsearch_pagerange">
                    <xsl:value-of select="$dictionaryPageRange-ShowingResults"/>
                    <xsl:text> </xsl:text>
                    <xsl:value-of select="$startMatch"/>
                    <xsl:if test="$startMatch != $endMatch">
                      <xsl:text> </xsl:text>
                      <xsl:value-of select="$dictionaryPageRange-To"/>
                      <xsl:text> </xsl:text>
                      <xsl:value-of select="$endMatch"/>
                    </xsl:if>
                  </span>
                </xsl:if>
              </xsl:if>
            </p>

            <!-- Now we need to sort the pages by score/relevance before sending them to the screen.
               We'll cycle through matched nodes once to save their pageScore in a variable -->
            <xsl:variable name="pageScoreList">
              <xsl:text>;</xsl:text>
              <xsl:for-each select="$matchedNodes">
                <!-- unique id for this node -->
                <xsl:value-of select="generate-id(.)"/>
                <xsl:text>=</xsl:text>
                <!-- weighted score for the matches -->
                <xsl:call-template name="pageScore">
                  <xsl:with-param name="item" select="."/>
                </xsl:call-template>
                <xsl:text>;</xsl:text>
              </xsl:for-each>
            </xsl:variable>

            <!-- display search results to the screen -->
            <div id="xsltsearch_results">
              <xsl:if test="count($matchedNodes) = 0">
                <xsl:text disable-output-escaping="yes"> </xsl:text>
              </xsl:if>

              <xsl:for-each select="$matchedNodes">
                <!--
    sort on the page score of the node, within ALL the nodes to return (the
    sorting must happen before choosing the nodes for this page) -->

                <xsl:sort select="substring-before(substring-after($pageScoreList, concat(';',generate-id(.),'=')),';')" data-type="number" order="descending"/>

                <!-- only the nodes for this page -->
                <xsl:if test="position() &gt;= $startMatch and position() &lt;= $endMatch">

                  <div class="xsltsearch_result">
                    <p class="xsltsearch_result_title">
                      <!-- show the ordinal number for this result -->
                      <xsl:if test="$showOrdinals != '0'">
                        <span class="xsltsearch_ordinal">
                          <xsl:value-of select="position()"/>
                          <xsl:text>.&nbsp;</xsl:text>
                        </span>
                      </xsl:if>

                      <!-- page name and url -->
                      <a href="{umbraco.library:NiceUrl(@id)}" class="xsltsearch_title">
                        <xsl:value-of select="@nodeName"/>
                      </a>

                      <!-- show the pageScore/relevance rating -->
                      <xsl:if test="$showScores != '0'">
                        <span class="xsltsearch_score">
                          <xsl:text> (</xsl:text>
                          <xsl:value-of select="$dictionaryScore-Score"/>
                          <xsl:text>: </xsl:text>
                          <xsl:value-of select="substring-before(substring-after($pageScoreList, concat(';',generate-id(.),'=')),';')"/>
                          <xsl:text>)</xsl:text>
                        </span>
                      </xsl:if>
                    </p>

                    <xsl:variable name="displayField">
                      <xsl:call-template name="displayFieldText">
                        <xsl:with-param name="item" select="."/>
                        <xsl:with-param name="fieldList" select="$previewFields"/>
                      </xsl:call-template>
                    </xsl:variable>

                    <!-- contents of search result -->
                    <xsl:variable name="strippedHTML" select="umbraco.library:StripHtml($displayField)"/>

                    <xsl:variable name="escapedData">
                      <xsl:choose>
                        <!-- display content of the search result, if available -->
                        <xsl:when test="string($strippedHTML) != ''">
                          <xsl:value-of select="$strippedHTML"/>
                        </xsl:when>
                      </xsl:choose>
                    </xsl:variable>

                    <!-- prepare for highlighting the search term within the search results by surrounding it with 'strong' tags -->
                    <xsl:variable name="before">&lt;strong&gt;</xsl:variable>
                    <xsl:variable name="after">&lt;/strong&gt;</xsl:variable>

                    <!-- display a portion of the page's text -->
                    <!-- display first words of the text -->
                    <xsl:if test="$previewType = 'BEGINNING' and string-length($escapedData &gt; 0)">
                      <p class="xsltsearch_result_description">
                        <span class="xsltsearch_description">
                          <xsl:value-of select="PS.XSLTsearch:surround(PS.XSLTsearch:escapingIntelligentSubstring($escapedData, 0, $previewChars), $search, $before, $after)" disable-output-escaping="yes"/>
                          <!-- add an elipsis if there is more text than we are showing on the search results page -->
                          <xsl:if test="string-length($escapedData) &gt; $previewChars">...</xsl:if>
                        </span>
                      </p>
                    </xsl:if>

                    <!-- or, display the actual place(s) where the search term was found and highlight them in context
                         providing a few words on either side of the search term. -->
                    <xsl:if test="$previewType = 'CONTEXT' and string-length($escapedData &gt; 0)">
                      <p class="xsltsearch_result_description">
                        <span class="xsltsearch_description">
                          <i>
                            <xsl:value-of select="$dictionaryDescription-Context"/>
                            <xsl:text>: </xsl:text>
                          </i>
                          <xsl:variable name="context" select="PS.XSLTsearch:contextOfFind(string($escapedData), $search, 5, 5, $previewChars)"/>
                          <xsl:choose>
                            <xsl:when test="string($context) != ''">
                              <xsl:value-of select="PS.XSLTsearch:surround($context, $search, $before, $after)" disable-output-escaping="yes"/>
                            </xsl:when>
                            <xsl:otherwise>
                              <i>
                                <xsl:value-of select="$dictionaryDescription-ContextUnavailable"/>
                              </i>
                            </xsl:otherwise>
                          </xsl:choose>
                        </span>
                      </p>
                    </xsl:if>

                    <!--
    OPTIONAL: include any additional information regarding the search
    result you want to display, such as createDate, updateDate, author, etc.
    -->


                  </div>
                </xsl:if>

              </xsl:for-each>
            </div>

            <!-- display paging navigation links, if needed -->
            <xsl:if test="$resultsPerPage &lt; count($matchedNodes)">
              <xsl:call-template name="searchNavigation">
                <xsl:with-param name="page" select="$page"/>
                <xsl:with-param name="matchedNodes" select="$matchedNodes"/>
              </xsl:call-template>
            </xsl:if>

          </xsl:if>

          <!-- display search box at the bottom of the page (the search box is always present even if no search was attempted) -->
          <xsl:if test="$searchBoxLocation='BOTTOM' or $searchBoxLocation='BOTH' or ($searchBoxLocation!='NONE' and $unescapedSearch ='')">
            <div class="xsltsearch_form">
              <input name="search" type="text" class="input">
                <xsl:attribute name="value">
                  <xsl:value-of select="$unescapedSearch"/>
                </xsl:attribute>
              </input>
              <xsl:text>&nbsp;</xsl:text>
              <input type="submit" class="submit">
                <xsl:attribute name="value">
                  <xsl:value-of select="$dictionaryButton-Search"/>
                </xsl:attribute>
              </input>
            </div>
          </xsl:if>

          <!-- display search execution time and stats -->
          <xsl:if test="$showStats != '0'">
            <xsl:if test="$search !=''">
              <p id="xsltsearch_stats">
                <xsl:value-of select="$dictionaryStats-Searched"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="count($possibleNodes)"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="$dictionaryStats-PagesIn"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="round(PS.XSLTsearch:getTimeSpan($startTime, PS.XSLTsearch:getTime())) div 1000"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="$dictionaryStats-Seconds"/>
              </p>
            </xsl:if>
          </xsl:if>

          <!--
    display XSLTsearch version information if in debug mode (that is, if
    the querystring contains umbDebugShowTrace=true) -->

          <xsl:if test="$showDebug != '0'">
            <p id="xsltsearch_debug">
              <xsl:text>XSLTsearch version </xsl:text>
              <xsl:value-of select="$XSLTsearchVersion"/>
            </p>
          </xsl:if>

          <!-- don't let a collapsed div tag break the page layout -->
          <xsl:if test="$unescapedSearch='' and $searchBoxLocation='NONE'">
            <xsl:text>&nbsp;</xsl:text>
          </xsl:if>
        </div>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="searchNavigation">
        <!-- navigation template (Note: we're just using hrefs with querystrings) -->
        <xsl:param name="page"/>
        <xsl:param name="matchedNodes"/>

        <p id="xsltsearch_navigation">
          <!-- previous page -->
          <a id="previous">
            <xsl:choose>
              <xsl:when test="$page &lt;= 1">
                <xsl:attribute name="class">disabled</xsl:attribute>
              </xsl:when>
              <xsl:otherwise>
                <xsl:attribute name="href">
                  <xsl:text>?search=</xsl:text>
                  <xsl:value-of select="$search"/>
                  <xsl:text>&amp;page=</xsl:text>
                  <xsl:value-of select="$page - 1"/>
                </xsl:attribute>
              </xsl:otherwise>
            </xsl:choose>
            <xsl:text>&lt; </xsl:text>
            <xsl:value-of select="$dictionaryNavigation-Previous"/>
          </a>
          <xsl:text>&nbsp;&nbsp;</xsl:text>

          <!-- each paged set of results is listed, with a link to that page set -->
          <xsl:call-template name="pageNumbers">
            <xsl:with-param name="pageIndex" select="1"/>
            <xsl:with-param name="page" select="$page"/>
            <xsl:with-param name="matchedNodes" select="$matchedNodes"/>
          </xsl:call-template>

          <!-- next page -->
          <xsl:text>&nbsp;</xsl:text>
          <a id="next">
            <xsl:choose>
              <xsl:when test="$page * $resultsPerPage &gt;= count($matchedNodes)">
                <xsl:attribute name="class">disabled</xsl:attribute>
              </xsl:when>
              <xsl:otherwise>
                <xsl:attribute name="href">
                  <xsl:text>?search=</xsl:text>
                  <xsl:value-of select="$search"/>
                  <xsl:text>&amp;page=</xsl:text>
                  <xsl:value-of select="$page + 1"/>
                </xsl:attribute>
              </xsl:otherwise>
            </xsl:choose>
            <xsl:value-of select="$dictionaryNavigation-Next"/>
            <xsl:text> &gt;</xsl:text>
          </a>
        </p>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="pageNumbers">
        <!-- paged results template -->
        <xsl:param name="page"/>
        <xsl:param name="pageIndex"/>
        <xsl:param name="matchedNodes"/>

        <xsl:variable name="distanceFromCurrent" select="$pageIndex - $page"/>

        <xsl:choose>
          <xsl:when test="$pageIndex = $page">
            <!-- current paged set -->
            <strong>
              <xsl:value-of select="$pageIndex"/>
            </strong>
            <xsl:text>&nbsp;</xsl:text>
          </xsl:when>

          <!-- show a maximum of nine paged sets on either side of the current paged set; just like Google does it -->
          <xsl:when test="($distanceFromCurrent &gt; -10 and $distanceFromCurrent &lt; 10)">
            <a>
              <xsl:attribute name="href">
                <xsl:text>?search=</xsl:text>
                <xsl:value-of select="$search"/>
                <xsl:text>&amp;page=</xsl:text>
                <xsl:value-of select="$pageIndex"/>
              </xsl:attribute>
              <xsl:value-of select="$pageIndex"/>
            </a>
            <xsl:text>&nbsp;</xsl:text>
          </xsl:when>
        </xsl:choose>

        <!-- recursively call the template for all the paged sets -->
        <xsl:if test="$pageIndex * $resultsPerPage &lt; count($matchedNodes)">
          <xsl:call-template name="pageNumbers">
            <xsl:with-param name="pageIndex" select="$pageIndex + 1"/>
            <xsl:with-param name="page" select="$page"/>
            <xsl:with-param name="matchedNodes" select="$matchedNodes"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="pageScore">
        <xsl:param name="item"/>

        <!-- sum up scores for each of the attributes -->
        <xsl:variable name="scoreA">
          <xsl:call-template name="scoreAttributes">
            <xsl:with-param name="item" select="$item"/>
          </xsl:call-template>
        </xsl:variable>

        <!-- sum up scores for each of the data nodes -->
        <xsl:variable name="scoreD">
          <xsl:call-template name="scoreDataNodes">
            <xsl:with-param name="item" select="$item[@isDoc]/*[not(@isDoc) and contains($searchFields, concat(',',name(),','))]"/>
          </xsl:call-template>
        </xsl:variable>

        <xsl:value-of select="number($scoreA) + number($scoreD)"/>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="scoreAttributes">
        <xsl:param name="item"/>
        <xsl:param name="index" select="1"/>
        <xsl:param name="score" select="0"/>

        <!-- name of the attribute on which we're searching -->
        <xsl:variable name="attributeName" select="name($item/attribute::*[position()=$index])"/>

        <xsl:variable name="weighting">
          <xsl:if test="contains($searchFields, concat(',@',$attributeName,','))">
            <xsl:value-of select="PS.XSLTsearch:power(2, number(PS.XSLTsearch:hitCount(substring-after($searchFields,$attributeName), ','))-1)"/>
          </xsl:if>
        </xsl:variable>

        <!-- calculate the final, cumulative, weighted score for this field -->
        <xsl:variable name="thisScore">
          <xsl:choose>
            <xsl:when test="contains($searchFields, concat(',@',$attributeName,','))">
              <!-- only calculate when this is a field actually being searched -->
              <xsl:call-template name="scoreForBooleanSearch">
                <xsl:with-param name="weighting" select="$weighting"/>
                <xsl:with-param name="toSearch" select="umbraco.library:StripHtml(string($item/attribute::*[name()=$attributeName]))"/>
                <xsl:with-param name="searchTermList" select="concat($search, ' ')"/>
              </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>0</xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <xsl:choose>
          <xsl:when test="count(./attribute::*)=$index">
            <!-- all done; print out total weight score -->
            <xsl:value-of select="$score + $thisScore"/>
          </xsl:when>
          <xsl:otherwise>
            <!-- continue recursion for other fields -->
            <xsl:call-template name="scoreAttributes">
              <xsl:with-param name="item" select="$item"/>
              <xsl:with-param name="index" select="$index + 1"/>
              <xsl:with-param name="score" select="$score + $thisScore"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="scoreForBooleanSearch">
        <xsl:param name="weighting" select="1"/>
        <xsl:param name="toSearch"/>
        <xsl:param name="searchTermList"/>
        <xsl:param name="currentHitCount" select="0"/>

        <!-- next search term -->
        <xsl:variable name="searchTerm">
          <xsl:value-of select="PS.XSLTsearch:getFirstElement($searchTermList, ' ')"/>
        </xsl:variable>

        <!-- remaining search terms -->
        <xsl:variable name="remainingSearchTermList">
          <xsl:value-of select="PS.XSLTsearch:removeFirstElement($searchTermList, ' ')"/>
        </xsl:variable>

        <!-- hit count for this search term -->
        <xsl:variable name="thisHitCount">
          <xsl:value-of select="PS.XSLTsearch:hitCount($toSearch, string($searchTerm))"/>
        </xsl:variable>

        <xsl:choose>
          <xsl:when test="string-length($remainingSearchTermList) &gt; 1">
            <!-- continue to search the rest of the terms -->
            <xsl:call-template name="scoreForBooleanSearch">
              <xsl:with-param name="weighting" select="$weighting"/>
              <xsl:with-param name="toSearch" select="$toSearch"/>
              <xsl:with-param name="searchTermList" select="$remainingSearchTermList"/>
              <xsl:with-param name="currentHitCount" select="$currentHitCount + $thisHitCount"/>
            </xsl:call-template>
          </xsl:when>

          <xsl:otherwise>
            <!-- finished searching: return the total hit count * weighting -->
            <xsl:value-of select="number($currentHitCount + $thisHitCount) * $weighting"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="scoreDataNodes">
        <xsl:param name="item"/>
        <xsl:param name="score" select="0"/>

        <!-- the weighting to apply to hits in this search field -->
        <xsl:variable name="weighting" select="PS.XSLTsearch:power(2, number(PS.XSLTsearch:hitCount(substring-after($searchFields,string(name($item))), ','))-1)"/>

        <!-- calculate the final, cumulative, weighted score for this field -->
        <xsl:variable name="thisScore">
          <xsl:choose>
            <xsl:when test="contains($searchFields, concat(',',name($item),','))">
              <!-- only calculate when this is a field actually being searched -->
              <xsl:call-template name="scoreForBooleanSearch">
                <xsl:with-param name="weighting" select="$weighting"/>
                <xsl:with-param name="toSearch" select="umbraco.library:StripHtml(string($item))"/>
                <xsl:with-param name="searchTermList" select="concat($search, ' ')"/>
              </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>0</xsl:otherwise>
          </xsl:choose>
        </xsl:variable>

        <!-- remaining data nodes whose hitCounts we need to tally; for recursion use -->
        <xsl:variable name="remaining" select="$item/following-sibling::*[not(@isDoc) and contains($searchFields, concat(',',name(),','))]"/>
        <xsl:choose>
          <xsl:when test="count($remaining) = 0">
            <!-- all done; return the final score -->
            <xsl:value-of select="number($thisScore) + number($score)"/>
          </xsl:when>
          <xsl:otherwise>
            <!-- keep summing the hitCounts for all the fields for this page by calling the pageScore template recursively -->
            <xsl:call-template name="scoreDataNodes">
              <xsl:with-param name="item" select="$remaining[position()=1]"/>
              <xsl:with-param name="score" select="number($thisScore) + number($score)"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="displayFieldText">
        <xsl:param name="item"/>
        <xsl:param name="fieldList"/>

        <xsl:variable name="fieldName">
          <xsl:value-of select="PS.XSLTsearch:getFirstElement($fieldList, ',')"/>
        </xsl:variable>
        <xsl:variable name="remainingFields">
          <xsl:value-of select="PS.XSLTsearch:removeFirstElement($fieldList, ',')"/>
        </xsl:variable>

        <xsl:if>
          <!-- actually print out field, if it exists and has content -->
               <xsl:if test="count($item/*[not(@isDoc)
    and name()=string($fieldName)]) = 1 and string($item/*[not(@isDoc) and
    name()=string($fieldName)]) != ''"
    >
            <xsl:value-of select="string($item/*[not(@isDoc) and name()=string($fieldName)])"/>
          </xsl:if>

          <xsl:if test="$remainingFields != ''">
            <!-- if this element does not exist, go on to the next one -->
            <xsl:call-template name="displayFieldText">
              <xsl:with-param name="item" select="$item"/>
              <xsl:with-param name="fieldList" select="$remainingFields"/>
            </xsl:call-template>
          </xsl:if>
        </xsl:if>
      </xsl:template>


      <!-- ============================================================= -->


      <xsl:template name="booleanAndMatchedNodes">
        <xsl:param name="yetPossibleNodes"/>
        <xsl:param name="searchTermList"/>

        <xsl:variable name="searchTerm">
          <xsl:value-of select="PS.XSLTsearch:unescapeString(PS.XSLTsearch:getFirstElement($searchTermList, ' '))"/>
        </xsl:variable>
        <xsl:variable name="remainingSearchTermList">
          <xsl:value-of select="PS.XSLTsearch:removeFirstElement($searchTermList, ' ')"/>
        </xsl:variable>

        <xsl:variable name="searchFieldsAttribsOnly">
          <xsl:variable name="sf" select="umbraco.library:Split($searchFields, ',')" />
          <xsl:for-each select="$sf//value">
            <xsl:if test="substring(., 1, 1) = '@'">
              <xsl:text>,</xsl:text>
              <xsl:value-of select="substring-after(., '@') "/>
              <xsl:text>,</xsl:text>
            </xsl:if>
          </xsl:for-each>
        </xsl:variable>

        <xsl:variable name="attribNodes" select="$yetPossibleNodes[@isDoc
                                                      and attribute::*[
                                                              contains($searchFieldsAttribsOnly,concat(',', name(), ','))
                                                              and contains(PS.XSLTsearch:uppercase(PS.XSLTsearch:unescapeString(umbraco.library:StripHtml(string(.)))), $searchTerm)
                                                              ]
                                                      ]" />

        <xsl:variable name="propertyNodes" select="$yetPossibleNodes/*[count(@isDoc) = 0
                                                      and contains($searchFields,concat(',', name(), ','))
                                                      and contains(PS.XSLTsearch:uppercase(PS.XSLTsearch:unescapeString(umbraco.library:StripHtml(string(.)))), $searchTerm)
                                                      ]/.." />

        <xsl:variable name="evenYetPossibleNodes" select="$attribNodes | $propertyNodes" />

        <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:choose>
                  <xsl:when test="@isDoc">
                    <xsl:value-of select="@id"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="../@id"/>
                  </xsl:otherwise>
                </xsl:choose>
                <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>


      <!-- ============================================================= -->

    </xsl:stylesheet>
  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Mar 09, 2011 @ 13:11
    Douglas Robar
    0

    I've found the problem that the original poster (William) reported and am working on a patch.

    BTW, it has nothing to do with <xsl:choose> and <xsl:if>. It is a bug in the escapingIntelligentSubstring() function.

    cheers,
    doug.

  • Djan Blom 99 posts 161 karma points
    Mar 09, 2011 @ 13:12
    Djan Blom
    0

    Thanks doug, I might have been sidetracked :)

  • William Schwartz 16 posts 85 karma points
    Mar 09, 2011 @ 15:17
    William Schwartz
    0

    That's great to hear Doug. Looking forward to the update.

    Thanks again.

  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Mar 09, 2011 @ 16:58
    Douglas Robar
    0

    I will get out an update shortly, but could you replace the existing escapingIntelligentSubstring() function in the /app_code/XSLTsearch.cs file with that shown below and let me know if that resolves the problem for you? It does in my testing.

    You'll want to restore the XSLTsearch.xslt file to its original condition if you modified it.

    public string escapingIntelligentSubstring(string data, int unescapedStart, int unescapedLength)
    {
        // zero-based, so reduce the length by one
        unescapedLength--;
    
        int unescapedPosition = 0;
        int escapedPosition = 0;
        int escapedStart = -1;
    
        data = data.TrimStart();
    
        while (escapedPosition < data.Length)
        {
            // left-trim of spaces and non-breaking-spaces
            if (escapedStart == -1 && unescapedPosition >= unescapedStart)
                if (data.Substring(escapedPosition, 1) != " " && data.Substring(escapedPosition, 1) != "&")
                {
                    // save the "escaped" starting point, taking into account escaped characters
                    escapedStart = escapedPosition;
                    unescapedPosition = 0;
                }
            if (data.Substring(escapedPosition, 1) == "&" && data.IndexOf(";", escapedPosition) > -1)
            {
                // look for an escaped character
                string escapedCharacter = data.Substring(escapedPosition, data.IndexOf(";", escapedPosition) - escapedPosition + 1);
                if (System.Text.RegularExpressions.Regex.Match(escapedCharacter, "&[A-Za-z]{2,6};").Success)
                    escapedPosition += escapedCharacter.Length;
                else
                    escapedPosition++;
            }
            else
            {
                escapedPosition++;
            }
    
            if (escapedStart > -1 && unescapedPosition - unescapedStart == unescapedLength)
                break;
    
            unescapedPosition++;
        }
    
        if (escapedStart == -1)
            // in case escapedStart was never set because all text was trimmed off
            return "";
    
        if (escapedPosition < data.Length)
            return data.Substring(escapedStart, escapedPosition - escapedStart) + "...";
        else
            return data.Substring(escapedStart, escapedPosition - escapedStart);
    
    }
    

    cheers,
    doug.

  • William Schwartz 16 posts 85 karma points
    Mar 09, 2011 @ 17:26
    William Schwartz
    0

    Doug,

    Just updated the CS file and so far it looks good (fixed). If anything crops up I'll let you know.

    Thanks for looking into this. It's really appreciated.

    -Wm

  • Djan Blom 99 posts 161 karma points
    Mar 10, 2011 @ 08:49
    Djan Blom
    0

    Sigh,

    I reinstalled XSLTSearch package, to make sure its clean. Swapped the code in the XSLTSearch.cs file, and STILL got the error " Error parsing XSLT file: \xslt\XSLTsearch.xslt"...

  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Mar 10, 2011 @ 10:38
    Douglas Robar
    0

    Hi, Djan,

    Your problem is a more fundamental and not related to this specific issue. Looking at the page you linked to (thanks for that!) and adding the ?umbDebugShowTrace=true querystring you can see the error at http://djan.v5.baseshop.dk/?umbDebugShowTrace=true

    Cannot find a script or an extension object associated with namespace 'urn:PS.XSLTsearch'.

    That error occurs when using Umbraco 4.6.x and XSLTsearch 3 because of a bug in the app_code XSLT extension handler. It has been fixed for Umbraco 4.7. Until then, you'll need to have the mvc dll to make it work properly. 

     

    Short answer is: click here to download the dll, and then copy it into the /bin folder of your website. 

     

    Details and full discussion in this thread: http://our.umbraco.org/projects/website-utilities/xsltsearch/xsltsearch-bugs/17941-Cannot-find-a-script-or-an-extension-object-associated-with-namespace-'urnPSXSLTsearch'

    cheers,
    doug.

  • Djan Blom 99 posts 161 karma points
    Mar 10, 2011 @ 12:13
    Djan Blom
    0

    Hi Doug,

    I see, I had been reading about the dll-file.

    I followed your instuctions, and placed the DLL inside the Bin folder - and now the Searchbar actually appears normal. But nothing happens when i click the Search button ?

    Also, I follewed this thread ( http://our.umbraco.org/projects/website-utilities/xsltsearch/xsltsearch-bugs/17353-Why-30-need-to-install-mvc-I-think-this-is-a-bug

    added this to my webconfig file. :

      <dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
    </dependentAssembly>

    however, now the site crashes with this error :

    Configuration Error


    Description: An error occurred during the processing
    of a configuration file required to service this request. Please review
    the specific error details below and modify your configuration file
    appropriately.

    Parser Error Message: Could not load file or
    assembly 'System.Web.Mvc' or one of its dependencies. The located
    assembly's manifest definition does not match the assembly reference.
    (Exception from HRESULT: 0x80131040)
    (C:\Baseshop\Umbraco4.6.2\Djan\build\web.config line 70)



    Source Error:
    Line 68:       <!-- URL REWRTIER -->
    Line 69: <add name="UrlRewriteModule" type="UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter" />
    Line 70: <add name="umbracoRequestModule" type="umbraco.presentation.requestModule" />
    Line 71: <!-- UMBRACO -->
    Line 72: <add name="viewstateMoverModule" type="umbraco.presentation.viewstateMoverModule" />
    Source File: C:\Baseshop\Umbraco4.6.2\Djan\build\web.config    Line: 70

     

    So, what to do with "line 70"? :)

    Thanks for the help so far, its really great !

     

    /Djan

  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Mar 10, 2011 @ 14:52
    Douglas Robar
    0

    Hi, Djan,

    IF you're using mvc3 you would want those entries in the web.config but do NOT put the mvc dll in the /bin folder because the dll I linked to is for mvc2.

    IF you're using mvc2 then just put the dll in the /bin folder and don't make any changes to web.config.

    That should make XSLTsearch bring up the search field and when you search, bring back some results (search for a single letter, for instance, as a test). As long as you don't get errors then you've got the dll and web.config set up correctly.

    If XSLTsearch works but doesn't return results as you expected then you'll want to set the XSLTsearch parameters for your specific site (where to search, what document type properties to search, etc.). All the options are explained in the PDF documentation for XSLTsearch. 

    cheers,
    doug.

  • Djan Blom 99 posts 161 karma points
    Mar 10, 2011 @ 15:01
    Djan Blom
    0

    Hi,

    Okay, I downloadet the dll file you posted - and changed my webconfig back the way it was.

    http://djan.v5.baseshop.dk/

    Try to hit the search, and please tell me why nothing happens? It doesnt return anything.I tried both in FF and IE.

    this is my macro, for what its worth.

    <umbraco:Macro source="1386" searchFields="@nodeName,pageTitle,bodyText" previewFields="bodyText,pageTitle" searchBoxLocation="BOTTOM" previewType="BEGINNING" resultsPerPage="5" previewChars="100" showPageRange="1" showOrdinals="0" showScores="0" showStats="0" Alias="XSLTsearch" runat="server"></umbraco:Macro>

     

    /djan

  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Mar 10, 2011 @ 15:10
    Douglas Robar
    0

    You are so close to getting this working!

    First things first though... the http://djan.v5.baseshop.dk/search.aspx page gives an error because the XSLTsearch template is for a default Runway installation, which you don't have. You'll want to update the 'Master' template dropdown and the content in the XSLTsearch template to be more like that for your TextPage template. 

    You will also want to include <form runat="server"> .... </form> around the XSLTsearch macro in the XSLTsearch template. As the troubleshooting section of the documentation says, you need to provide your own <form> tags.

    With the corrected XSLTsearch template and <form> tag the http://djan.v5.baseshop.dk/search.aspx page will display a search form and at least some search results and XSLTsearch is working properly.

     

    The second thing is to make the search field in the top of your web pages work properly. Again, you'll need a <form> tag. For this one, I would recommend you use an html form rather than a .net form so that you can specify the action location. <form action="/search.aspx" method="get"> ... </form>

     

    Treat these as two different steps. First make the search page work, then make the site-wide search field work and redirect to the search page.

    cheers,
    doug.

     

  • Djan Blom 99 posts 161 karma points
    Mar 11, 2011 @ 10:38
    Djan Blom
    0

    EUREKA!!! :D Thanks Doug!

    the form-tags did the trick!, now its just the template - and some styling.
    But Im really glad for the help you guys gave!

     

    Have a nice weekend!

    /Djan

  • Richard Oatridge 1 post 21 karma points
    Mar 11, 2011 @ 12:13
    Richard Oatridge
    0

    Doug,

    Thanks for the great search tool ... and for posting the updated CS for this issue ... I'd been scratching my head on this one, but the new CS appears to have solved the issue for me!

     

    Thanks,

    Richard. 

Please Sign in or register to post replies

Write your reply to:

Draft