RE: [xsl] xsl search engine

Subject: RE: [xsl] xsl search engine
From: Jarno.Elovirta@xxxxxxxxx
Date: Thu, 11 Mar 2004 19:56:45 +0200
Hi,

> Recapitulation of the problem
> I want to search a string in a xml file and display the matched nodes.
> 
> The XML document looks like this :
> <LIST>
> 	<THEME label="Droit du travail" id="12"/>
> 	<THEME label="droit social" id="2"/>
> 	<THEME label="travail à la chaîne" id="34"/>
> 	<THEME label="rien du tout" id="17"/>
> </LIST>
> 
> The search engine only search on the labels attribute of the 
> THEME nodes of
> this xml document and it display the @label.

...

> The second problem is (it's less nescessary but would be great) :
> I'd like to highlight the searched words in the displayed 
> result...how to ?
Turn the matching process around

  <xsl:param name="string" select="'droit travail'"/>
  <xsl:template name="tokenizer">
    <xsl:param name="text" select="normalize-space($string)"/>
    <xsl:choose>
      <xsl:when test="contains($text, ' ')">
        <xsl:choose>
          <xsl:when test="contains(@label, substring-before($text, ' '))">true</xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="tokenizer">
              <xsl:with-param name="text" select="substring-after($text, ' ')"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="$text and contains(@label, $text)">true</xsl:when>
    </xsl:choose>
  </xsl:template>
  <xsl:template name="highlight">
    <xsl:param name="label" select="@label"/>
    <xsl:param name="text" select="normalize-space($string)"/>
    <xsl:choose>
      <xsl:when test="contains($text, ' ')">
        <xsl:variable name="current" select="substring-before($text, ' ')"/>
        <xsl:choose>
          <xsl:when test="contains($label, $current)">
            <xsl:call-template name="highlight">
              <xsl:with-param name="label"  select="substring-before($label, $current)"/>
              <xsl:with-param name="text" select="substring-after($text, ' ')"/>
            </xsl:call-template>
            <em>
              <xsl:value-of select="$current"/>
            </em>
            <xsl:call-template name="highlight">
              <xsl:with-param name="label"  select="substring-after($label, $current)"/>
              <xsl:with-param name="text" select="substring-after($text, ' ')"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="highlight">
              <xsl:with-param name="label" select="$label"/>
              <xsl:with-param name="text" select="substring-after($text, ' ')"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="$text">
        <xsl:choose>
          <xsl:when test="contains($label, $text)">
            <xsl:value-of select="substring-before($label, $text)"/>
            <em>
              <xsl:value-of select="$text"/>
            </em>
            <xsl:value-of select="substring-after($label, $text)"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$label"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <xsl:template match="LIST">
    <form action="display.asp" method="post">
      <input type="text" name="UserString"/>
      <input type="submit" value="Go!"/>
    </form>
    <xsl:for-each select="THEME">
      <xsl:variable name="match">
        <xsl:call-template name="tokenizer"/>
      </xsl:variable>
      <xsl:if test="string($match)">
        <xsl:call-template name="highlight"/>
        <br/>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

Using extensions would probably make the code shorter, e.g. just output highlighting into a variable, cast that into a node-set and test if it contains an em element to see if its a match.

Cheers,

Jarno - VNV Nation: Genesis

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread