XSLT - removing a tag from within text

G

gwoodhouse

Hi All,

This should be so easy but is so incredibly not easy that im about
ready to kill myself.

What i have is this xml:
<node>
<start_time>00:00:<span class="hit">11</span></start_time>
</node>

and i just want it to output:
00:00:00

Luckily for me XSLT is ridiculous, making this problem unsolvable.

i've tried:
fn:substring-before(start_time, "<")
but of course, thats far too straight forward so it doesnt work.

I've tried:
<xsl:apply-templates select="start_time"/>
<xsl:template match="span">
</xsl:template>
but of course, that, although esoteric, doesn't work either

I've tried string(start_time), i've even tried to do fn:escape-uri and
tried to replace those values but that doesnt work either!

Please someone for the love of all that is good in this world help
me!!!!!
 
M

Martin Honnen

What i have is this xml:
<node>
<start_time>00:00:<span class="hit">11</span></start_time>
</node>

and i just want it to output:
00:00:00

This is easy:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:eek:utput method="text"/>

<xsl:template match="/">
<xsl:apply-templates select="node/start_time"/>
</xsl:template>

</xsl:stylesheet>
 
P

Philippe Poulard

Martin Honnen a écrit :
This is easy:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:eek:utput method="text"/>

<xsl:template match="/">
<xsl:apply-templates select="node/start_time"/>
</xsl:template>

</xsl:stylesheet>

this one should work too:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:eek:utput method="text"/>

</xsl:stylesheet>

--
Cordialement,

///
(. .)
--------ooO--(_)--Ooo--------
| Philippe Poulard |
-----------------------------
http://reflex.gforge.inria.fr/
Have the RefleX !
 
G

gwoodhouse

Ok, so, i can't include the whole code or else my company would beat
the hell out of me. Here is a more complete and realworld snippet:

<transcript>
<chapter>
<chapter_hitcount><![CDATA[1 hit]]></chapter_hitcount>
<start_time><![CDATA[01:11:04]]></start_time>
<end_time><![CDATA[01:<span class="hit">22</span>:45]]></end_time>
<abstract> You can see here how you would want <span
class="hit">22</span> to be displayed</abstract>
</chapter>
</transcript>

xslt:
<xsl:template match='chapter'>
<span class="timespan">
(<xsl:apply-templates select="start_time"/> - <xsl:apply-templates
select="end_time"/>)
</span>
<div class="abstract">
<span class="abstractLead">Summary:</span> <xsl:apply-templates
select="abstract"/>
</div>
</xsl:template>

In this example i would want the output to display the "abstract"
output with the span tag, i would want the "end_time" tag to display
without the <span> tag.
 
M

Martin Honnen

Ok, so, i can't include the whole code or else my company would beat
the hell out of me. Here is a more complete and realworld snippet:

<transcript>
<chapter>
<chapter_hitcount><![CDATA[1 hit]]></chapter_hitcount>
<start_time><![CDATA[01:11:04]]></start_time>
<end_time><![CDATA[01:<span class="hit">22</span>:45]]></end_time>
<abstract> You can see here how you would want <span
class="hit">22</span> to be displayed</abstract>
</chapter>
</transcript>

xslt:
<xsl:template match='chapter'>
<span class="timespan">
(<xsl:apply-templates select="start_time"/> - <xsl:apply-templates
select="end_time"/>)
</span>
<div class="abstract">
<span class="abstractLead">Summary:</span> <xsl:apply-templates
select="abstract"/>
</div>
</xsl:template>

In this example i would want the output to display the "abstract"
output with the span tag, i would want the "end_time" tag to display
without the <span> tag.

Well that is completely different from what you posted before and in the
sample above the 'abstract' element contains a 'span' element while the
'end_time' element does not contain a 'span' element, instead it
contains pure text with escaped markup.

The 'abstract' element can easily be solved with XSLT

<xsl:template match="abstract">
<div class="{local-name()}">
<xsl:apply-templates/>
</div>
</xsl:template>

then you need to add a template matching span that copies that

<xsl:template match="span">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

The 'end_time' element is difficult. If I had a choice I would solve it
with XSLT 2.0 and David Carlisle's HTML parser done in XSLT
(http://www.dcarlisle.demon.co.uk/htmlparse.xsl) but I don't know
whether that is an option for you.
 
G

gwoodhouse

Yeah, problem is none of that works.

There are lots of places where many many values need to print out a
<span> tag.

What i want is a way of removing <span class="hit"> from the output of
ONE tag.

Please someone tell me there is a way of doing that, not by changing
the way everything else works, just by removing the damn <span> tag
from one output.

Surely, SURELY, XSLT can manage to create a variable from "a bit of
<span>text</span>" that contains "a bit of text".

Surely?!?!
 
G

gwoodhouse

So, basically, i want this:

end_time contents: 00:00:<span class="hit">11</span>

<xsl:variable name="safeend">
<xsl:call-template name="removeSpan">
<xsl:with-param name="variable" select="end_time"/>
</xsl:call-template>
</xsl:variable>

<xsl:template name="removeSpan">
<xsl:param name="variable"/>
<xsl:value-of select="fn:substring-before($variable, '<')"/>
</xsl:template>

with safeend being: 00:00:11

Yes it's in a CDATA tag but that doesn't seem to change anything at
all.
 
G

gwoodhouse

None of what?

<xsl:template match="span">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

would make a global change to the functionality of the XSLT (not that
this actually seems to do anything at all even if it did work)

All i want is a nice simple string/node change. On just one node. When
i tell it to. Everywhere else in the XSLT it's doing exactly as it
should, the only thing i need to change is outputting the end_time
field WITHOUT <span>.
 
P

Philippe Poulard

(e-mail address removed) a écrit :
<xsl:template match="span">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

would make a global change to the functionality of the XSLT (not that
this actually seems to do anything at all even if it did work)

All i want is a nice simple string/node change. On just one node. When
i tell it to. Everywhere else in the XSLT it's doing exactly as it
should, the only thing i need to change is outputting the end_time
field WITHOUT <span>.

you don't have a <span> node, you just have a <span> text; just use
string manipulation functions such as substring-before() and
substring-after() that are available in xslt 1.0 for that purpose

something like this:

<xsl:template match='end_time'>
<xsl:value-of select="substring-before(.,'<span')"/>
<xsl:value-of
select="substring-before(substring-after(.,'>'),'</span>'"/>
<xsl:value-of select="substring-after(.,'</span>')"/>
</xsl:template>

very ugly

--
Cordialement,

///
(. .)
--------ooO--(_)--Ooo--------
| Philippe Poulard |
-----------------------------
http://reflex.gforge.inria.fr/
Have the RefleX !
 
G

gwoodhouse

you don't have a said:
string manipulation functions such as substring-before() and
substring-after() that are available in xslt 1.0 for that purpose

If only it were that easy -

I get the error message:
Line #100; Column #57; org.xml.sax.SAXParseException: The value of
attribute "select" associated with an element type "xsl:value-of" must
not contain the '<' character.

and putting &lt; gives a stack overflow exception as it seems to make
the proccessor recurse continually.
 
P

Philippe Poulard

(e-mail address removed) a écrit :
If only it were that easy -

I get the error message:
Line #100; Column #57; org.xml.sax.SAXParseException: The value of
attribute "select" associated with an element type "xsl:value-of" must
not contain the '<' character.

you're right, i forgot to escape it:

<xsl:template match='end_time'>
<xsl:value-of select="substring-before(.,'&lt;span')"/>
<xsl:value-of
select="substring-before(substring-after(.,'&gt;'),'&lt;/span&gt;'"/>
<xsl:value-of select="substring-after(.,'&lt;/span&gt;')"/>
and putting &lt; gives a stack overflow exception as it seems to make
the proccessor recurse continually.

this template doesn't recurse; check elsewhere how it is invoked

to make it run alone, change the template that matches the root:

<xsl:template match='/'>
<xsl:apply-templates select="//end_time"/>
</xsl:template>

after the last <xsl:value-of>, you also might find useful to add \n :
<xsl:text>
</xsl:text>

--
Cordialement,

///
(. .)
--------ooO--(_)--Ooo--------
| Philippe Poulard |
-----------------------------
http://reflex.gforge.inria.fr/
Have the RefleX !
 
M

Mayeul

So, basically, i want this:
>
[snip]

Yes it's in a CDATA tag but that doesn't seem to change anything at
all.

Actually, it changes just about everything. By definition, there are no
elements in a CDATA tag. XSLT is mainly designed to operate with XPath
rules, not with raw text.
 
J

Joe Kesselman

As others have said, that isn't "a tag in text" -- it's text which
happens to look like a tag. Your only option is string manipulation.
 
J

Joe Kesselman

Note too that putting "tags" in text is generally Bad Practice unless
you really want the visible representation of a tag rather than an
actual element. If you're writing an XML/HTML tutorial, what you're
doing may make sense. If that isn't what you're doing, this is probably
not saying what you want it to say.
 
G

gwoodhouse

Dunno where you guys work but i'd love the choice of what data i
get :)

I'm sorry to say this, but again, using string manipulation just isn't
working.
Here's my code:
<xsl:template name="removeSpan">
<xsl:param name="variable"/>
<xsl:if test="contains($variable, 'span')"><xsl:text>value:</
xsl:text></xsl:if>
<xsl:value-of select="substring-before($variable, 'span')"/>
<xsl:value-of select="substring-after($variable, 'hit&quot;')"/>
<xsl:text>jim</xsl:text><xsl:value-of select="$variable"/>
</xsl:template>

Here's the output:
jim01:
<span class="hit">
22
</span>
:45

As you can see it doesn't even like "span" ?! (i of course tried this
with &lt; and even < first)

Anyone see why this is going wrong?
 
G

gwoodhouse

i can however pull back:
01:<span class="hit">

if i try and do:
substring-before($variable, "22").
 
G

gwoodhouse

i can however pull back:
01:<span class="hit">

if i try and do:
substring-before($variable, "22").

Ahem, yes, found the problem. The output was going through a proccess
i was unaware of, converting [mkup][mkup] tags to <span class="hit"></
span>.

So, yeah er, problem solved. Reason i couldn't just manipulate the
string to get rid of <span> was that it wasn't there.

Yes, i deserve your scorn (and pity).

Thats a day i'll never get back again :(

Thanks for your help though i guess.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top