Subject: Re: [xsl] substring-before doesn't copy node From: Marco <spinmar@xxxxxxxxx> Date: Fri, 12 Jan 2007 14:51:28 +0100 |
Hi, sorry for my mail but I thought that my problem was clear. :-[ Following your advice, I wrote the following template which should be used to highligh one or more words inside a string. My template has a problem: if the string has two times the same word only the first is highlighted. Suppose to have a simple XML:
<?xml version="1.0" encoding="UTF-8"?> <Root> <Query>pippo pluto</Query> <Url>http://dominio.com/pippo/pluto.html</Url> </Root>
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date exsl" xmlns:str="http://exslt.org/strings" exclude-result-prefixes="str" xmlns:exsl="http://exslt.org/common" version="1.0">
<xsl:variable name="xsltsl-str-lower" select="'abcdefgh� 069;jklmnopqr& #x0073;tuvwxyzµ 0;áâãäåæçèé&#x 00EA;ëìíîïðñòó ôõöøùúûüý� FE;ÿāăąćĉċčď&# x0111;ēĕėęěĝğġģ ;ĥħĩīĭįıijĵ� 137;ĺļľŀłńņňŋ& #x014D;ŏőœŕŗřśŝ F;šţťŧũūŭůű&#x 0173;ŵŷźżžſƃƅƈ ƌƒƕƙơƣƥƨƭ B0;ƴƶƹƽƿDždžLjlj&# x01CB;njǎǐǒǔǖǘǚǜ ;ǝǟǡǣǥǧǩǫǭ� 1EF;Dzdzǵǹǻǽǿȁȃ& #x0205;ȇȉȋȍȏȑȓȕ! 7;șțȝȟȣȥȧȩȫ&#x 022D;ȯȱȳɓɔɖɗəɛ ɠɣɨɩɯɲɵʀʃ 88;ʊʋʒͅάέήία&# x03B2;γδεζηθικλ ;μνξοπρςστ� 3C5;φχψωϊϋόύώ& #x03D0;ϑϕϖϛϝϟϡϣ> 5;ϧϩϫϭϯϰϱϲϵ&#x 0430;бвгдежзий клмнопрст 43;фхцчшщъыь&# x044D;юяѐёђѓєѕі ;їјљњћќѝўџ� 461;ѣѥѧѩѫѭѯѱѳ& #x0475;ѷѹѻѽѿҁҍҏI 1;ғҕҗҙқҝҟҡң&#x 04A5;ҧҩҫҭүұҳҵҷ ҹһҽҿӂӄӈӌӑ D3;ӕӗәӛӝӟӡӣӥ&# x04E7;өӫӭӯӱӳӵӹա ;բգդեզէըթժ� 56B;լխծկհձղճմ& #x0575;նշոչպջռսW E;տրցւփքօֆḁ&#x 1E03;ḅḇḉḋḍḏḑḓḕ ḗḙḛḝḟḡḣḥḧ 29;ḫḭḯḱḳḵḷḹḻ&# x1E3D;ḿṁṃṅṇṉṋṍṏ ;ṑṓṕṗṙṛṝṟṡ E63;ṥṧṩṫṭṯṱṳṵ& #x1E77;ṹṻṽṿẁẃẅẇǨ 9;ẋẍẏẑẓẕẛạả&#x 1EA5;ầẩẫậắằẳẵặ ẹẻẽếềểễệỉ CB;ọỏốồổỗộớờ&# x1EDF;ỡợụủứừửữự ;ỳỵỷỹἀἁἂἃἄ F05;ἆἇἐἑἒἓἔἕἠ& #x1F21;ἢἣἤἥἦἧἰἱdz 2;ἳἴἵἶἷὀὁὂὃ&#x 1F44;ὅὑὓὕὗὠὡὢὣ ὤὥὦὧὰάὲέὴ 75;ὶίὸόὺύὼώᾀ&# x1F81;ᾂᾃᾄᾅᾆᾇᾐᾑᾒ ;ᾓᾔᾕᾖᾗᾠᾡᾢᾣ FA4;ᾥᾦᾧᾰᾱᾳιῃῐ& #x1FD1;ῠῡῥῳⅰⅱⅲⅳȗ 4;ⅵⅶⅷⅸⅹⅺⅻⅼⅽ&#x 217E;ⅿⓐⓑⓒⓓⓔⓕⓖⓗ ⓘⓙⓚⓛⓜⓝⓞⓟⓠ$ E1;ⓢⓣⓤⓥⓦⓧⓨⓩa&# xFF42;cdefghijk ;lmnopqrst F55;vwxyz𐐨𐐩𐐪Ą 2B;𐐬𐐭𐐮𐐯𐐰𐐱𐐲𐐳&# x10434;𐐵𐐶𐐷𐐸𐐹𐐺𐐻၃ C;𐐽𐐾𐐿𐑀𐑁𐑂𐑃𐑄&#x 10445;𐑆𐑇𐑈𐑉𐑊𐑋𐑌𐑍 ;'"/> <xsl:variable name="xsltsl-str-upper" select="'ABCDEFGH� 049;JKLMNOPQR& #x0053;TUVWXYZΜ 0;ÁÂÃÄÅÆÇÈÉ&#x 00CA;ËÌÍÎÏÐÑÒÓ ÔÕÖØÙÚÛÜÝ� DE;ŸĀĂĄĆĈĊČĎ&# x0110;ĒĔĖĘĚĜĞĠĢ ;ĤĦĨĪĬĮIIJĴ� 136;ĹĻĽĿŁŃŅŇŊ& #x014C;ŎŐŒŔŖŘŚŜ E;ŠŢŤŦŨŪŬŮŰ&#x 0172;ŴŶŹŻŽSƂƄƇ ƋƑǶƘƠƢƤƧƬ AF;ƳƵƸƼǷDŽDŽLJLJ&# x01CA;NJǍǏǑǓǕǗǙǛ ;ƎǞǠǢǤǦǨǪǬ� 1EE;DZDZǴǸǺǼǾȀȂ& #x0204;ȆȈȊȌȎȐȒȔ! 6;ȘȚȜȞȢȤȦȨȪ&#x 022C;ȮȰȲƁƆƉƊƏƐ ƓƔƗƖƜƝƟƦƩ AE;ƱƲƷΙΆΈΉΊΑ&# x0392;ΓΔΕΖΗΘΙΚΛ ;ΜΝΞΟΠΡΣΣΤ� 3A5;ΦΧΨΩΪΫΌΎΏ& #x0392;ΘΦΠϚϜϞϠϢ> 4;ϦϨϪϬϮΚΡΣΕ&#x 0410;БВГДЕЖЗИЙ КЛМНОПРСТ 23;ФХЦЧШЩЪЫЬ&# x042D;ЮЯЀЁЂЃЄЅІ ;ЇЈЉЊЋЌЍЎЏ� 460;ѢѤѦѨѪѬѮѰѲ& #x0474;ѶѸѺѼѾҀҌҎI 0;ҒҔҖҘҚҜҞҠҢ&#x 04A4;ҦҨҪҬҮҰҲҴҶ ҸҺҼҾӁӃӇӋӐ D2;ӔӖӘӚӜӞӠӢӤ&# x04E6;ӨӪӬӮӰӲӴӸԱ ;ԲԳԴԵԶԷԸԹԺ� 53B;ԼԽԾԿՀՁՂՃՄ& #x0545;ՆՇՈՉՊՋՌՍT E;ՏՐՑՒՓՔՕՖḀ&#x 1E02;ḄḆḈḊḌḎḐḒḔ ḖḘḚḜḞḠḢḤḦ 28;ḪḬḮḰḲḴḶḸḺ&# x1E3C;ḾṀṂṄṆṈṊṌṎ ;ṐṒṔṖṘṚṜṞṠ E62;ṤṦṨṪṬṮṰṲṴ& #x1E76;ṸṺṼṾẀẂẄẆǨ 8;ẊẌẎẐẒẔṠẠẢ&#x 1EA4;ẦẨẪẬẮẰẲẴẶ ẸẺẼẾỀỂỄỆỈ CA;ỌỎỐỒỔỖỘỚỜ&# x1EDE;ỠỢỤỦỨỪỬỮỰ ;ỲỴỶỸἈἉἊἋἌ F0D;ἎἏἘἙἚἛἜἝἨ& #x1F29;ἪἫἬἭἮἯἸἹdz A;ἻἼἽἾἿὈὉὊὋ&#x 1F4C;ὍὙὛὝὟὨὩὪὫ ὬὭὮὯᾺΆῈΈῊ CB;ῚΊῸΌῪΎῺΏᾈ&# x1F89;ᾊᾋᾌᾍᾎᾏᾘᾙᾚ ;ᾛᾜᾝᾞᾟᾨᾩᾪᾫ FAC;ᾭᾮᾯᾸᾹᾼΙῌῘ& #x1FD9;ῨῩῬῼⅠⅡⅢⅣȖ 4;ⅥⅦⅧⅨⅩⅪⅫⅬⅭ&#x 216E;ⅯⒶⒷⒸⒹⒺⒻⒼⒽ ⒾⒿⓀⓁⓂⓃⓄⓅⓆ$ C7;ⓈⓉⓊⓋⓌⓍⓎⓏA&# xFF22;CDEFGHIJK ;LMNOPQRST F35;VWXYZ𐐀𐐁𐐂Ą 03;𐐄𐐅𐐆𐐇𐐈𐐉𐐊𐐋&# x1040C;𐐍𐐎𐐏𐐐𐐑𐐒𐐓၁ 4;𐐕𐐖𐐗𐐘𐐙𐐚𐐛𐐜&#x 1041D;𐐞𐐟𐐠𐐡𐐢𐐣𐐤𐐥 ;'"/> <xsl:variable name="xsltsl-str-digits" select="'0123456789'"/> <!-- space (#x20) characters, carriage returns, line feeds, or tabs. --> <xsl:variable name="xsltsl-str-ws" select="' 	
'"/>
<xsl:template name="iol_make_lower"> <xsl:param name="text"/> <xsl:value-of select="translate($text, $xsltsl-str-upper, $xsltsl-str-lower)"/> </xsl:template>
<xsl:template name="highlighter"> <xsl:param name="text"/> <xsl:param name="what"/>
<xsl:variable name="test-text"> <xsl:call-template name="iol_make_lower"> <xsl:with-param name="text" select="$text" /> </xsl:call-template> </xsl:variable>
<xsl:choose> <xsl:when test="contains($test-text, exsl:node-set($what)/token[1])"> <xsl:variable name="before" select="substring-before(string($test-text), exsl:node-set($what)/token[1])"/> <xsl:variable name="after" select="substring-after($test-text, exsl:node-set($what)/token[1])"/> <xsl:variable name="real-before" select="substring($text, 1, string-length($before))"/> <xsl:variable name="real-after" select="substring($text, string-length($before) + string-length(exsl:node-set($what)/token[1]) + 1)"/>
<xsl:variable name="temp"> <xsl:value-of select="concat($real-before, '<b>', exsl:node-set($what)/token[1], '</b>', $real-after)" /> </xsl:variable>
<xsl:choose> <xsl:when test="count(exsl:node-set($what)/token[position() > 1] ) = 0"> <xsl:value-of select="$temp" disable-output-escaping="yes" /> </xsl:when> <xsl:otherwise> <xsl:call-template name="highlighter"> <xsl:with-param name="text"><xsl:copy-of select="$temp" /></xsl:with-param> <xsl:with-param name="what"><xsl:copy-of select="exsl:node-set($what)/token[position() > 1]" /></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="position() = last()"> <xsl:value-of select="$text" disable-output-escaping="yes" /> </xsl:when> <xsl:otherwise> <xsl:call-template name="highlighter"> <xsl:with-param name="text"><xsl:copy-of select="$text" /></xsl:with-param> <xsl:with-param name="what"><xsl:copy-of select="exsl:node-set($what)/token[position() > 1]" /></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template>
<xsl:template name="main_highlighter"> <xsl:param name="query"/> <xsl:param name="url"/>
<xsl:variable name="url_decoded"> <xsl:value-of select="str:decode-uri($url)" /> <!--<xsl:value-of select="$url" />--> </xsl:variable>
<xsl:variable name="test-what"> <xsl:call-template name="iol_make_lower"> <xsl:with-param name="text" select="$query" /> </xsl:call-template> </xsl:variable>
<xsl:choose> <xsl:when test="normalize-space($test-what)"> <xsl:variable name="pp"> <xsl:copy-of select="str:tokenize(string($test-what), ' ')" /> </xsl:variable> <xsl:call-template name="highlighter"> <xsl:with-param name="text"><xsl:value-of select="$url_decoded" /></xsl:with-param> <xsl:with-param name="what"><xsl:copy-of select="$pp"/></xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$url_decoded" /> </xsl:otherwise> </xsl:choose> </xsl:template>
<xsl:template match="/"> <xsl:apply-templates select ="Root"/> </xsl:template>
<xsl:template match="Root"> <html> <head> <title>Temp</title> </head> <body> <p> <xsl:call-template name="main_highlighter"> <xsl:with-param name="query"><xsl:value-of select="Query" /></xsl:with-param> <xsl:with-param name="url"><xsl:value-of select="Url" /></xsl:with-param> </xsl:call-template> </p> </body> </html> </xsl:template>
In this case all is ok, but if the url is <Url>http://dominio.com/pippo/pippo/pluto.html</Url> the output is:
... <p>http://dominio.com/<b>pippo</b>/pippo/<b>pluto</b>.html</p> .....
What could I do? I'm using libxslt 1.1.15 as xslt engine. Best regards
byYou seem to be confused about the data model. Your title mentions "nodes", but your message mentions "tags"; you seem to be in a state where you half-know that the input is represented as a tree but you're still mentally behaving as if it's all a single string in which elements are represented
textual markup.to
You haven't really said what $test-text is, but my guess is that it's an element node with three children, namely a text node containing http://dominio.com/, an element node named b whose content is pippo, and a text node whose content is /pluto.html. When you apply substring-before()
ofan element node, it converts the first argument to a string, which is done by taking the string-value of the element node. This is the concatenation
all the text node descendants, namely"http://dominio.com/pippo/pluto.html".
toSo you lose the hierarchic structure of the input (or, as you put it, the "tags").
If you want to process the text while retaining the structure of the tree, then flattening the structure into a string isn't going to help. You need
process each text node individually. Of course, some things are going to be very difficult to achieve, like highlighting the string "com/pip" which straddles two nodes. Your first task is to specify what you want the output to be in such cases.
Michael Kay http://www.saxonica.com/
-----Original Message----- From: Marco [mailto:spinmar@xxxxxxxxx] Sent: 12 January 2007 09:36 To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Subject: [xsl] substring-before doesn't copy node
Hi, I'm writing a recursive template and I have some problems with subtring-before. I'm trying to write a words highlighter. In my template if my text contains the word I'm looking for, I write:
<xsl:variable name="before" select="substring-before($test-text, .)" /> <xsl:variable name="after" select="substring-after($test-text, .)"/> <xsl:variable name="real-before" select="substring($text, 1, string-length($before))"/> <xsl:variable name="real-after" select="substring($text, string-length($before) + string-length(.) + 1)"/>
The problem is that my test-text contains for example http://dominio.com/<b>pippo</b>/pluto.html and I'm looking for pluto, the before string is http://dominio.com/pippo/. It seems that substring-before deletes my tag <b></b>. I suppose that the problem is in the substring-after too. I tried to write: <xsl:variable name="before"><xsl:copy-of select="substring-before($test-text, .)" /></xsl:variable> but the problem remains. How could I solve my problem? Best regards Marco
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] substring-before doesn't , Michael Kay | Thread | [xsl] Adding *xmlns* attribute dyna, Kishore Bankupelle |
Re: [xsl] Adding *xmlns* attribute , David Carlisle | Date | Re: [xsl] document($RssXmlFeed) not, Web Developer |
Month |