URL parsing and replacing

J

jamesfin

Dear XMLers,


Please guide me...


I have a simple xml file...


<URLTest>
<text1>My favorite news site is http://www.yahoo.com</text1>
<text2>My favorite software site is
http://www.microsoft.com</text2>
</URLTest>


Using this XML, how do I extract the url using XSLT so that the
resulting html contains the following...

My favorite news site is <a
href="http://www.yahoo.com">http://www.yahoo.com</a>

My favorite software site is <a
href="http://www.yahoo.com">http://www.microsoft.com</a>

The text entered is free form so I won't know ahead of time if a URL
exists in the input text field or not. It's not required but it would
be nice to create the link for them if it is there.

It is essentially replacing the http://... with the href code.

Netman
 
K

Keith Davies

Dear XMLers,


Please guide me...


I have a simple xml file...


<URLTest>
<text1>My favorite news site is http://www.yahoo.com</text1>
<text2>My favorite software site is
http://www.microsoft.com</text2>
</URLTest>


Using this XML, how do I extract the url using XSLT so that the
resulting html contains the following...

My favorite news site is <a
href="http://www.yahoo.com">http://www.yahoo.com</a>

My favorite software site is <a
href="http://www.yahoo.com">http://www.microsoft.com</a>

The text entered is free form so I won't know ahead of time if a URL
exists in the input text field or not. It's not required but it would
be nice to create the link for them if it is there.

It is essentially replacing the http://... with the href code.

<xsl:template match='text()'>
<xsl:call-template name='grab-url'>
<xsl:with-param name='s' select='.' />
</xsl:call-template>
</xsl:template>

<xsl:template name='grab-url'>
<xsl:param name='s' />
<xsl:variable name='pre' select='string-before($s,"http://")' />
<xsl:variable name='test' select='string-after($s,"http://")' />
<xsl:variable name='addr' select='string-before($test," ")' />
<xsl:variable name='post' select='string-after($test," ")' />
<xsl:variable name='url'>
<xsl:choose>
<xsl:when test='$addr'>http://<xsl:value-of select='$addr'
/></xsl:when>
<xsl:when test='$test'>http://<xsl:value-of select='$test'
/></xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test='$pre'>
<xsl:value-of select='$pre'>
<a href='{$url}'><xsl:value-of select='$url' /></a>
<xsl:if test='$post'><xsl:call-template name='grab-url'>
<xsl:with-param name='s' select='concat(" ",$post)' />
</xsl:call-template></xsl:if>
</xsl:when>
<xsl:eek:therwise><xsl:value-of select='$s' /></xsl:eek:therwise>
</xsl:choose>
</xsl:template>


Should do it. I've expanded the elements a bit to make it more
readable; it may be necessary to collapse things and remove whitespace
to ensure you don't get bogus spaces in the output text.


Keith
 
J

jamesfin

Thanks for the code!

Using my existing xslt, how do I integrate this code? The @result in
my code below has the original string to display with the possible URL
embedded in it.



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<div align="center">
<p><img src="logo.gif"></img></p>
<p><font size="+1" face="Verdana, Arial, Helvetica,
sans-serif"></font></p>
</div>
<table border="0" align="center">
<tr>
<td align="left" bgcolor="638EC3">
<div align="center">
<font color="#FFFFFF" size="-1" face="Verdana, Arial,
Helvetica, sans-serif">Step</font>
</div>
</td>
<td align="left" bgcolor="638EC3">
<font color="#FFFFFF" size="-1" face="Verdana, Arial, Helvetica,
sans-serif">Test Results</font>
</td>
</tr>
<xsl:for-each select="application/steps/step">
<xsl:choose>
<xsl:when test="(@pass='PASS')">
<tr >
<td bgcolor="638EC3">
<div align="center"><font color="#FFFFFF" size="-1"
face="Verdana, Arial, Helvetica, sans-serif">
<xsl:value-of select="@id"/>
</font>
</div>
</td>
<td bgcolor="#80FF80">
<div align="{@align}">
<font size="-1" face="Verdana, Arial, Helvetica,
sans-serif">
<xsl:value-of select="@result"
disable-output-escaping="yes"/>
</font>
</div>
</td>
</tr>
</xsl:when>
<xsl:when test="(@pass='Pass')">
<tr >
<td bgcolor="638EC3">
<div align="center"><font color="#FFFFFF" size="-1"
face="Verdana, Arial, Helvetica, sans-serif">
<xsl:value-of select="@id"/>
</font>
</div>
</td>
<td bgcolor="#FFFF80">
<div align="{@align}">
<font size="-1" face="Verdana, Arial, Helvetica, sans-serif">
<xsl:value-of select="@result"/>
</font>
</div>
</td>
</tr>
</xsl:when>
<xsl:when test="(@pass='Fail')">
<tr >
<td bgcolor="638EC3">
<div align="center"><font color="#FFFFFF" size="-1"
face="Verdana, Arial, Helvetica, sans-serif">
<xsl:value-of select="@id"/>
</font>
</div>
</td>
<td bgcolor="#FF8080">
<div align="{@align}">
<font size="-1" face="Verdana, Arial, Helvetica, sans-serif">
<xsl:value-of select="@result"/>
</font>
</div>
</td>
</tr>
</xsl:when>
<xsl:eek:therwise>
<tr>
<td>
<div align="center"> <font size="-1" face="Verdana,
Arial, Helvetica, sans-serif">
<xsl:value-of select="@id"/>
</font>
</div>
</td>
<td bgcolor="#FFFF80">
<div align="{@align}">
<font size="-1" face="Verdana, Arial, Helvetica, sans-serif">
<xsl:value-of select="@result"/>
</font>
</div>
</td>
</tr>
</xsl:eek:therwise>
</xsl:choose>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
 
K

Keith Davies

Thanks for the code!

Using my existing xslt, how do I integrate this code? The @result in
my code below has the original string to display with the possible URL
embedded in it.

Oh? If that's the case, just call grab-url. What I wrote should work
on *all* text() in the document (but not attribute values).

Where you process @result, do:

<xsl:call-template name='grab-url'>
<xsl:with-param name='s' select='@result' />
</xsl:call-template>

instead of

<xsl:value-of select='@result' />

You could instead do

<xsl:template match='@result'>
<xsl:call-template name='grab-url'>
<xsl:with-param name='s' select='.' />
</xsl:call-template>
</xsl:template>

then change

<xsl:value-of select='@result' />

to

<xsl:apply-templates select='@result' />


It all depends what you're doing.


Keith
 
J

jamesfin

Getting close!

I'm now getting an 'xsl-value-of may not contain a.' error. Is the
'url' parameter being set or used?

If I remove this section of code, it generates okay.

<xsl:choose>
<xsl:when test='$pre'>
<xsl:value-of select='$pre'>

<a href='{$url}'> <xsl:value-of select='$url' /> </a>
<xsl:if test='$post'>
<xsl:call-template name='grab-url'>
<xsl:with-param name='s' select='concat(" ",$post)' />
</xsl:call-template>
</xsl:if>

</xsl:value-of>
</xsl:when>
<xsl:eek:therwise><xsl:value-of select='$s' /></xsl:eek:therwise>
</xsl:choose>
 
J

jamesfin

I did notice that there must be a space in front of the http://... to
work even if it's the first thing on a line of text. Anyway of getting
around this limitation?

Thanks!
 
K

Keith Davies

I did notice that there must be a space in front of the http://... to
work even if it's the first thing on a line of text. Anyway of getting
around this limitation?

Actually, it doesn't need a space before the http://, it just has to
have *something*.

Look for "test='$pre'". You'll see the instruction to output the $url
value. Move that instruction (and everything after it, to the end of
the "test='$pre'" condition) to immediately following the condition.

That is, it should do

<xsl:if test='$pre'><!-- do $pre stuff --></xsl:if>
<xsl:if test='$url'><!-- do $url stuff --></xsl:if>
<xsl:if test='$post'><!-- do $post stuff --></xsl:if>

rather than

<xsl:if test='$pre'>
<!-- do $pre stuff -->
<!-- do $url stuff -->
<!-- do $post stuff -->
</xsl:if>

(though I think I used xsl:when there; don't remember and you didn't
quote)


Keith
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top