Subject: RE: Highlighting words/phrases
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 28 Jul 2006 22:56:24 +0100
|
OK, I see now what you were trying to achieve. Not a problem I would relish
tackling in XSLT 1.0.
Michael Kay
http://www.saxonica.com/
> -----Original Message-----
> From: yguaba@xxxxxxxxxxxx [mailto:yguaba@xxxxxxxxxxxx]
> Sent: 28 July 2006 18:00
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re: Highlighting words/phrases
>
> On 27 Jul 2006 at 22:54:21, Michael Kay wrote:
>
> > If you change your code so that it makes a recursive call
> on "highlight"
> > in place of the call on "search-and-replace" (whose function is
> > unclear from your description), then it will highlight all
> the occurrences.
>
> You're right, of course, Michael: I was adapting another
> template and forgot to change the name in the recursion. It's
> always an honour to get a reply from you, but that wasn't
> really the issue.
>
> My problem was that the template only highlighted the first
> word or phrase from the list (i.e. the first "keyword"
> element), whereas what I needed was something that would
> iterate through *all* the keyword elements, check whether
> their text was present in the "contents"
> element, and, if so, enclose the matching bit as in this example:
> <span class="highlight">matching bit</span>.
>
> I ended up figuring out that a for-each loop wouldn't work,
> as it would keep concatenating the same bits of the input
> string that had already been checked for the presence of the
> previous key word. In the end I concluded that the only
> viable solution would be to recurse.
>
> After much testing and tweaking, I got the little monster
> below to do what I need. If anyone has any suggestions on
> ways to simplify and/or optimize this template, it would be
> great to hear them.
>
> Cheers,
>
> Erik
>
> ------------------------
> T E M P L A T E
> ------------------------
>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xsi:schemaLocation="http://www.w3.org/1999/XSL/Transform
> http://www.w3.org/2004/11/schema-for-xslt20.xsd">
> <xsl:output method="html" indent="yes" encoding="utf-8"/>
>
> <xsl:variable name="lower-case"
> select="'abcdefg�
> 68;ijklmnop&#x
> 0071;rstuvwxy&
> #x007A;µàáâãäåæ
> ;çèéêëìíî�
> EF;ðñòóôõöø&#x
> 00F9;úûüýþÿāă&
> #x0105;ćĉċčďđēĕ
> ;ėęěĝğġģĥ
> 27;ĩīĭįıijĵķ&#x
> 013A;ļľŀłńņňŋ&
> #x014D;ŏőœŕŗřśŝ
> ;şšţťŧũūŭ
> 6F;űųŵŷźżžſ&#x
> 0183;ƅƈƌƒƕƙơƣ&
> #x01A5;ƨƭưƴƶƹƽƿ
> ;DždžLjljNjnjǎǐ
> D2;ǔǖǘǚǜǝǟǡ&#x
> 01E3;ǥǧǩǫǭǯDzdz&
> #x01F5;ǹǻǽǿȁȃȅȇ
> ;ȉȋȍȏȑȓȕȗ
> 19;țȝȟȣȥȧȩȫ&#x
> 022D;ȯȱȳɓɔɖɗə&
> #x025B;ɠɣɨɩɯɲɵʀ
> ;ʃʈʊʋʒͅάέ
> AE;ίαβγδεζη&#x
> 03B8;ικλμνξοπ&
> #x03C1;ςστυφχψω
> ;ϊϋόύώϐϑϕ
> D6;ϛϝϟϡϣϥϧϩ&#x
> 03EB;ϭϯϰϱϲϵаб&
> #x0432;гдежзийк
> ;лмнопрст
> 43;фхцчшщъы&#x
> 044C;эюяѐёђѓє&
> #x0455;іїјљњћќѝ
> ;ўџѡѣѥѧѩѫ
> 6D;ѯѱѳѵѷѹѻѽ&#x
> 047F;ҁҍҏґғҕҗҙ&
> #x049B;ҝҟҡңҥҧҩҫ
> ;ҭүұҳҵҷҹһ
> BD;ҿӂӄӈӌӑӓӕ&#x
> 04D7;әӛӝӟӡӣӥӧ&
> #x04E9;ӫӭӯӱӳӵӹա
> ;բգդեզէըթ
> 6A;իլխծկհձղ&#x
> 0573;մյնշոչպջ&
> #x057C;սվտրցւփք
> ;օֆḁḃḅḇḉḋ
> 0D;ḏḑḓḕḗḙḛḝ&#x
> 1E1F;ḡḣḥḧḩḫḭḯ&
> #x1E31;ḳḵḷḹḻḽḿṁ
> ;ṃṅṇṉṋṍṏṑ
> 53;ṕṗṙṛṝṟṡṣ&#x
> 1E65;ṧṩṫṭṯṱṳṵ&
> #x1E77;ṹṻṽṿẁẃẅẇ
> ;ẉẋẍẏẑẓẕẛ
> A1;ảấầẩẫậắằ&#x
> 1EB3;ẵặẹẻẽếềể&
> #x1EC5;ệỉịọỏốồổ
> ;ỗộớờởỡợụ
> E7;ứừửữựỳỵỷ&#x
> 1EF9;ἀἁἂἃἄἅἆἇ&
> #x1F10;ἑἒἓἔἕἠἡἢ
> ;ἣἤἥἦἧἰἱἲ
> 33;ἴἵἶἷὀὁὂὃ&#x
> 1F44;ὅὑὓὕὗὠὡὢ&
> #x1F63;ὤὥὦὧὰάὲέ
> ;ὴήὶίὸόὺύ
> 7C;ώᾀᾁᾂᾃᾄᾅᾆ&#x
> 1F87;ᾐᾑᾒᾓᾔᾕᾖᾗ&
> #x1FA0;ᾡᾢᾣᾤᾥᾦᾧᾰ
> ;ᾱᾳιῃῐῑῠῡ
> E5;ῳⅰⅱⅲⅳⅴⅵⅶ&#x
> 2177;ⅸⅹⅺⅻⅼⅽⅾⅿ&
> #x24D0;ⓑⓒⓓⓔⓕⓖⓗⓘ
> ;ⓙⓚⓛⓜⓝⓞⓟⓠ$
> E1;ⓢⓣⓤⓥⓦⓧⓨⓩ&#x
> FF41;bcdefghi&
> #xFF4A;klmnopqr
> ;stuvwxyz
> 428;𐐩𐐪𐐫𐐬𐐭𐐮𐐯&#x
> 10430;𐐱𐐲𐐳𐐴𐐵𐐶𐐷&
> #x10438;𐐹𐐺𐐻𐐼𐐽𐐾𐐿
> ;𐑀𐑁𐑂𐑃𐑄𐑅𐑆Ą
> 47;𐑈𐑉𐑊𐑋𐑌𐑍'"/>
> <xsl:variable name="upper-case"
> select="'ABCDEFG�
> 48;IJKLMNOP&#x
> 0051;RSTUVWXY&
> #x005A;ΜÀÁÂÃÄÅÆ
> ;ÇÈÉÊËÌÍÎ�
> CF;ÐÑÒÓÔÕÖØ&#x
> 00D9;ÚÛÜÝÞŸĀĂ&
> #x0104;ĆĈĊČĎĐĒĔ
> ;ĖĘĚĜĞĠĢĤ
> 26;ĨĪĬĮIIJĴĶ&#x
> 0139;ĻĽĿŁŃŅŇŊ&
> #x014C;ŎŐŒŔŖŘŚŜ
> ;ŞŠŢŤŦŨŪŬ
> 6E;ŰŲŴŶŹŻŽS&#x
> 0182;ƄƇƋƑǶƘƠƢ&
> #x01A4;ƧƬƯƳƵƸƼǷ
> ;DŽDŽLJLJNJNJǍǏ
> D1;ǓǕǗǙǛƎǞǠ&#x
> 01E2;ǤǦǨǪǬǮDZDZ&
> #x01F4;ǸǺǼǾȀȂȄȆ
> ;ȈȊȌȎȐȒȔȖ
> 18;ȚȜȞȢȤȦȨȪ&#x
> 022C;ȮȰȲƁƆƉƊƏ&
> #x0190;ƓƔƗƖƜƝƟƦ
> ;ƩƮƱƲƷΙΆΈ
> 89;ΊΑΒΓΔΕΖΗ&#x
> 0398;ΙΚΛΜΝΞΟΠ&
> #x03A1;ΣΣΤΥΦΧΨΩ
> ;ΪΫΌΎΏΒΘΦ
> A0;ϚϜϞϠϢϤϦϨ&#x
> 03EA;ϬϮΚΡΣΕАБ&
> #x0412;ГДЕЖЗИЙК
> ;ЛМНОПРСТ
> 23;ФХЦЧШЩЪЫ&#x
> 042C;ЭЮЯЀЁЂЃЄ&
> #x0405;ІЇЈЉЊЋЌЍ
> ;ЎЏѠѢѤѦѨѪ
> 6C;ѮѰѲѴѶѸѺѼ&#x
> 047E;ҀҌҎҐҒҔҖҘ&
> #x049A;ҜҞҠҢҤҦҨҪ
> ;ҬҮҰҲҴҶҸҺ
> BC;ҾӁӃӇӋӐӒӔ&#x
> 04D6;ӘӚӜӞӠӢӤӦ&
> #x04E8;ӪӬӮӰӲӴӸԱ
> ;ԲԳԴԵԶԷԸԹ
> 3A;ԻԼԽԾԿՀՁՂ&#x
> 0543;ՄՅՆՇՈՉՊՋ&
> #x054C;ՍՎՏՐՑՒՓՔ
> ;ՕՖḀḂḄḆḈḊ
> 0C;ḎḐḒḔḖḘḚḜ&#x
> 1E1E;ḠḢḤḦḨḪḬḮ&
> #x1E30;ḲḴḶḸḺḼḾṀ
> ;ṂṄṆṈṊṌṎṐ
> 52;ṔṖṘṚṜṞṠṢ&#x
> 1E64;ṦṨṪṬṮṰṲṴ&
> #x1E76;ṸṺṼṾẀẂẄẆ
> ;ẈẊẌẎẐẒẔṠ
> A0;ẢẤẦẨẪẬẮẰ&#x
> 1EB2;ẴẶẸẺẼẾỀỂ&
> #x1EC4;ỆỈỊỌỎỐỒỔ
> ;ỖỘỚỜỞỠỢỤ
> E6;ỨỪỬỮỰỲỴỶ&#x
> 1EF8;ἈἉἊἋἌἍἎἏ&
> #x1F18;ἙἚἛἜἝἨἩἪ
> ;ἫἬἭἮἯἸἹἺ
> 3B;ἼἽἾἿὈὉὊὋ&#x
> 1F4C;ὍὙὛὝὟὨὩὪ&
> #x1F6B;ὬὭὮὯᾺΆῈΈ
> ;ῊΉῚΊῸΌῪΎ
> FA;Ώᾈᾉᾊᾋᾌᾍᾎ&#x
> 1F8F;ᾘᾙᾚᾛᾜᾝᾞᾟ&
> #x1FA8;ᾩᾪᾫᾬᾭᾮᾯᾸ
> ;ᾹᾼΙῌῘῙῨῩ
> EC;ῼⅠⅡⅢⅣⅤⅥⅦ&#x
> 2167;ⅨⅩⅪⅫⅬⅭⅮⅯ&
> #x24B6;ⒷⒸⒹⒺⒻⒼⒽⒾ
> ;ⒿⓀⓁⓂⓃⓄⓅⓆ$
> C7;ⓈⓉⓊⓋⓌⓍⓎⓏ&#x
> FF21;BCDEFGHI&
> #xFF2A;KLMNOPQR
> ;STUVWXYZ
> 400;𐐁𐐂𐐃𐐄𐐅𐐆𐐇&#x
> 10408;𐐉𐐊𐐋𐐌𐐍𐐎𐐏&
> #x10410;𐐑𐐒𐐓𐐔𐐕𐐖𐐗
> ;𐐘𐐙𐐚𐐛𐐜𐐝𐐞Ą
> 1F;𐐠𐐡𐐢𐐣𐐤𐐥'"/>
>
> <xsl:template name="highlight">
> <xsl:param name="input"/>
> <xsl:param name="target"/>
> <xsl:param name="elem-name" select="'span'"/>
> <xsl:param name="class-name"/>
> <xsl:param name="caseless" select="true()"/>
> <xsl:choose>
> <xsl:when test="$caseless and $target[1]">
> <xsl:choose>
> <xsl:when
> test="contains(translate($input, $upper-case, $lower- case),
> translate($target[1], $upper-case, $lower-case))">
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input" select="substring( $input, 1,
> string-length(substring-before(translate($input, $upper-case,
> $lower- case), translate($target[1], $upper-case, $lower-case))) )"/>
>
> <xsl:with-param name="target" select="$target[position() > 1]"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
> </xsl:call-template>
> <xsl:element
> name="{$elem-name}">
>
> <xsl:attribute name="class">
>
> <xsl:value-of select="$class-name"/>
> </xsl:attribute>
>
> <xsl:value-of select="substring($input, string-
> length(substring-before(translate($input, $upper-case,
> $lower-case), translate($target[1], $upper-case,
> $lower-case))) + 1, string- length($target[1]))"/>
> </xsl:element>
> <xsl:choose>
>
> <xsl:when test="contains(substring-after(translate($input,
> $upper-case, $lower-case), translate($target[1], $upper-case,
> $lower- case)), translate($target[1], $upper-case, $lower-case))">
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input" select="substring($input,
> string-length(substring-before(translate($input, $upper-case,
> $lower- case), translate($target[1], $upper-case,
> $lower-case))) + string-
> length($target[1]) + 1)"/>
>
> <xsl:with-param name="target" select="$target"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
>
> </xsl:call-template>
> </xsl:when>
> <xsl:otherwise>
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input" select="substring($input,
> string-length(substring-before(translate($input, $upper-case,
> $lower- case), translate($target[1], $upper-case,
> $lower-case))) + string-
> length($target[1]) + 1)"/>
>
> <xsl:with-param name="target"
> select="$target[position() > 1]"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
>
> </xsl:call-template>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:when>
> <xsl:otherwise>
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input" select="$input"/>
>
> <xsl:with-param name="target" select="$target[position() > 1]"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
> </xsl:call-template>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:when>
> <xsl:when test="not($caseless) and $target[1]">
> <xsl:choose>
> <xsl:when
> test="contains($input, $target[1])">
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input" select="substring-before($input,
> $target[1])"/>
>
> <xsl:with-param name="target" select="$target[position() > 1]"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
>
> <xsl:with-param name="caseless" select="false()"/>
> </xsl:call-template>
> <xsl:element
> name="{$elem-name}">
>
> <xsl:attribute name="class">
>
> <xsl:value-of select="$class-name"/>
> </xsl:attribute>
>
> <xsl:value-of select="$target[1]"/>
> </xsl:element>
> <xsl:choose>
>
> <xsl:when test="contains(substring-after($input, $target[1]),
> $target[1])">
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input"
> select="substring-after($input, $target[1])"/>
>
> <xsl:with-param name="target" select="$target"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
>
> <xsl:with-param name="caseless" select="false()"/>
>
> </xsl:call-template>
> </xsl:when>
> <xsl:otherwise>
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input"
> select="substring-after($input, $target[1])"/>
>
> <xsl:with-param name="target"
> select="$target[position() > 1]"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
>
> <xsl:with-param name="caseless" select="false()"/>
>
> </xsl:call-template>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:when>
> <xsl:otherwise>
>
> <xsl:call-template name="highlight">
>
> <xsl:with-param name="input" select="$input"/>
>
> <xsl:with-param name="target" select="$target[position() > 1]"/>
>
> <xsl:with-param name="class-name" select="$class-name"/>
> </xsl:call-template>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:when>
> <xsl:otherwise>
> <xsl:value-of select="$input"/>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:template>
>
> </xsl:stylesheet>
>
>
>
> _______________________________________________________
> O Yahoo! esta de cara nova. Venha conferir!
> http://br.yahoo.com/preview
|