Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old June 13th, 2008, 09:57 AM
Registered User
 
Join Date: Jun 2008
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default Best approach to replace characters with strings

Hello!
I'm new to XSL/Xpath and would be glad if you could give me any advice!

A client of ours uses a program that generates a text file, whose fields are added in an XML structure. One of the nodes have the following information:

<MsgCantoInfEsq>@ Milhas }]# (Inlcuindo o limite de Empréstimo Fácil) ~</MsgCantoInfEsq>

I need to make this replacement:
- from '@' to <h1 class="label">
- from '}' to </h1>
- from ']' to <p class="espaco">
- from '#' to <p>
- from '~' to </p>


First, I tried using 'replace()'. For instance, replace(//MsgCantoInfEsq, '#', '&lt;p>'). Still, when the browser renders the code, it does not apply the style for this tag.

Then, I tried the following:

<xsl:variable name="msg" select="tokenize(//MsgCantoInfEsq, '\s+')"/>
<xsl:for-each select="$msg">
    <xsl:choose>
        <xsl:when test="$msg = '@'">
            <xsl:text><![CDATA[<h1 class="label">]]></xsl:text>
        </xsl:when>
        <xsl:when test="$teste = '}'">
            <xsl:text><![CDATA[</h1>]]></xsl:text>
        </xsl:when>
        <xsl:when test="$teste = ']'">
            <xsl:text><![CDATA[<p class="espaco">]]></xsl:text>
        </xsl:when>
        <xsl:when test="$teste = '#'">
            <xsl:text><![CDATA[<p>]]></xsl:text>
        </xsl:when>
        <xsl:when test="$teste = '~'">
            <xsl:text><![CDATA[</p>]]></xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="."/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:for-each>

I was expecting to get this:
<h class="label">Milhas</h>
<p class="espaco">
<p>(Inlcuindo o limite de Empréstimo Fácil)</p>

However, nothing is displayed. I'm using Saxon 8.

Could you please help me??

Thanks in advance!
 
Old June 13th, 2008, 10:06 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Whoever designed that format shouldn't be allowed near XML.
One of the problems is that you are creating text, not markup, so if you look at the raw output you will see the angle brackets are escaped.
In my opinion you'd be better off pre-processing with a text tool to replace the special symbols with there true counterparts but someone else may have a clever way of doing what you need from within XSLT.

--

Joe (Microsoft MVP - XML)
 
Old June 13th, 2008, 10:09 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

XSLT constructs a result tree which can contain element nodes e.g. h1 or p element nodes and these element nodes can have attribute nodes (like class). It is not working on a text level where you create start tags like <h1> or end tags like </h1>.
So you need to change your approach and create elements like h1 or p either as literal result elements
Code:
<h1>foo</h1>
or with xsl:element
Code:
<xsl:element name="h1">foo</xsl:element>
unless you want to resort to disable-output-escaping hacks.


--
  Martin Honnen
  Microsoft MVP - XML
 
Old June 13th, 2008, 10:36 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Your mistake is in the title of your post. You are not trying to replace the characters with strings, you are trying to replace them with element nodes. XSLT generates a tree of nodes, not lexical XML - never forget this!

Since you're using XSLT 2.0, the answer lies with xsl:analyze-string, which allows new element nodes to be constructed within the <xsl:matching-substring> instruction.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old June 16th, 2008, 03:18 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

All the above advice is correct, but on a completely different level, your RegEx is incorrect, as is your for-each loop.

$msg will be an array containing the following values:

Code:
@
Milhas
}]#
(Inlcuindo
o
limite
de
Empréstimo
Fácil)
~
None of the values in the array equals ']' or '}' or '#'.

Also, in your for-each loop the first test is testing $msg - which is the whole array. You then proceed to test $teste - a variable I see no declaration for (why this doesn't give you an error I don't know).



/- Sam Judson : Wrox Technical Editor -/
 
Old June 16th, 2008, 10:03 AM
Registered User
 
Join Date: Jun 2008
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I really appreciate all the replies!! Since Friday, I've been analyzing each one of them in order to better understand our options here. Also, I've been checking this site http://www.dpawson.co.uk and getting some ideas!

Sam, this may sound stupid, but could you please tell me why in my for-each loop the first test is testing the whole array, and what changes I have to do in order to start evaluating the first position instead of the entire array??
I tried another test, just to better understand how for-each works:

<xsl:variable name="teste" select="tokenize('tchau ola tchau', '\s')"/>
<xsl:for-each select="$teste">
    <xsl:choose>
        <xsl:when test="$teste = 'ola'">
            <xsl:text>Achei ola!</xsl:text>
        </xsl:when>
        <xsl:when test="$teste = 'tchau'">
            <xsl:text>Achei tchau!</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>Nao nada!</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:for-each>

I thought the output would be something like:
Achei tchau!
Achei ola!
Achei tchau!

However, I get:
Achei ola!
Achei ola!
Achei ola!

Btw, you were correct with the $test variable; when I posted the first message, I forgot changing '$teste' to '$msg'. Sorry!
 
Old June 16th, 2008, 10:08 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

I think you want
Code:
<xsl:variable name="teste" select="tokenize('tchau ola tchau', '\s')"/>
<xsl:for-each select="$teste">
    <xsl:choose>
        <xsl:when test=". = 'ola'">
            <xsl:text>Achei ola!</xsl:text>
        </xsl:when>
        <xsl:when test=". = 'tchau'">
            <xsl:text>Achei tchau!</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>Nao nada!</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:for-each>
--
  Martin Honnen
  Microsoft MVP - XML
 
Old June 16th, 2008, 10:12 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

If $teste is an array, then $teste = 'X' test to see if ANY element in the array equals 'X', i.e. in your example above for every loop through the for-each you are testing the WHOLE array again.

You want this:

Code:
<xsl:variable name="teste" select="tokenize('tchau ola tchau', '\s')"/>
<xsl:for-each select="$teste">
    <xsl:variable name="t" select="."/>
    <xsl:choose>
        <xsl:when test="$t = 'ola'">
            <xsl:text>Achei ola!</xsl:text>
        </xsl:when>
        <xsl:when test="$t = 'tchau'">
            <xsl:text>Achei tchau!</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>Nao nada!</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:for-each>
/- Sam Judson : Wrox Technical Editor -/
 
Old June 16th, 2008, 12:38 PM
Registered User
 
Join Date: Jun 2008
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks guys, I *really* appreciate your help!! And I told you the question was stupid..... sorry!!!





Similar Threads
Thread Thread Starter Forum Replies Last Post
Separating strings and replacing characters sunrain XSLT 4 April 7th, 2008 09:33 AM
Replace newline characters thomasjacob XML 1 May 2nd, 2006 04:06 AM
Find and Replace 2 characters at once!! HELP scovitch65 VB.NET 2002/2003 Basics 2 March 18th, 2006 01:40 AM
Need help with approach rickyc1 Classic ASP Databases 4 July 14th, 2005 10:26 AM
how to restrict strings with particular characters srini XSLT 6 November 28th, 2003 07:03 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.