[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: auto-hyperlinker (how to search/replace)?

Subject: Re: auto-hyperlinker (how to search/replace)?
From: Terence Kearns <terencek@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 30 May 2003 17:56:32 +1000
hyperlinker
Jeni Tennison wrote:
Hi Terence,


Is it possible to write some XSL code which will search some text()
for a URL pattern and replace it with a hyperlinked version of
itself.


Yes, but it's not particularly straight-forward. Creating a
"hyperlink" named template that takes a string and returns text nodes
and elements -- the elements being hyperlinks:

<xsl:template name="hyperlink">
  <xsl:param name="string" select="string()" />
  ...
</xsl:template>

The template needs to search for the first thing that looks like a
URL, so the string 'http://' will do nicely. If the string doesn't
contain the string 'http://' then it can just be output as-is:

<xsl:template name="hyperlink">
  <xsl:param name="string" select="string()" />
  <xsl:choose>
    <xsl:when test="contains($string, 'http://')">
      ...
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Anything before the 'http://', if it occurs, can just be output as a
text node:

<xsl:template name="hyperlink">
  <xsl:param name="string" select="string()" />
  <xsl:choose>
    <xsl:when test="contains($string, 'http://')">
      <xsl:value-of select="substring-before($string, 'http://')" />
      ...
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

The URL itself needs to be identified: taking the substring from the
'http://' to the next space will probably work:

<xsl:template name="hyperlink">
  <xsl:param name="string" select="string()" />
  <xsl:choose>
    <xsl:when test="contains($string, 'http://')">
      <xsl:value-of select="substring-before($string, 'http://')" />
      <xsl:variable name="rest"
                    select="substring-after($string, 'http://')" />
      <xsl:variable name="url"
        select="concat('http://', substring-before($rest, ' '))" />
      ...
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Then you can make the link around that URL:

<xsl:template name="hyperlink">
  <xsl:param name="string" select="string()" />
  <xsl:choose>
    <xsl:when test="contains($string, 'http://')">
      <xsl:value-of select="substring-before($string, 'http://')" />
      <xsl:variable name="rest"
                    select="substring-after($string, 'http://')" />
      <xsl:variable name="url"
        select="concat('http://', substring-before($rest, ' '))" />
      <a href="{$url}">
        <xsl:value-of select="$url" />
      </a>
      ...
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Finally, you need to move on to the rest of the string, after the URL,
and call the template (recursively) on that piece of the string, in
case there are any more URLs within it:

<xsl:template name="hyperlink">
  <xsl:param name="string" select="string()" />
  <xsl:choose>
    <xsl:when test="contains($string, 'http://')">
      <xsl:value-of select="substring-before($string, 'http://')" />
      <xsl:variable name="rest"
                    select="substring-after($string, 'http://')" />
      <xsl:variable name="url"
        select="concat('http://', substring-before($rest, ' '))" />
      <a href="{$url}">
        <xsl:value-of select="$url" />
      </a>
      <xsl:call-template name="hyperlink">
        <xsl:with-param name="string"
                        select="substring-after($rest, $url)" />
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

XSLT 2.0 makes this process a lot easier: you can use
<xsl:analyze-string> with regular expressions to do this kind of
string processing. In XSLT 2.0, the template would look more like:

<xsl:template name="hyperlink">
  <xsl:param name="string" select="string(.)" />
  <xsl:analyze-string select="$string"
                      regex="http://[^ ]+">
    <xsl:matching-substring>
      <a href="{.}">
        <xsl:value-of select="." />
      </a>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
      <xsl:value-of select="." />
    </xsl:non-matching-substring>
  </xsl:analyze-string>
</xsl:template>

and of course the regex for matching URLs could be a lot more
sophisticated.

Cheers,

Jeni


Wow. Thanks Jeni, I think it would have taken me a very long time to work that one out. I think I understand everything given that you've laid it all out for me. This approach will no-doubt be useful for many other applications such as auto-highlighting etc (good for keyword search results etc).


Thanks again.






XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.