This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Format text within a XML tag...
- From: Peter Davis <pdavis152 at attbi dot com>
- To: xsl-list at lists dot mulberrytech dot com
- Cc: "Anders Wasen" <a_wasen at hotmail dot com>
- Date: Tue, 18 Jun 2002 03:02:52 -0700
- Subject: Re: [xsl] Format text within a XML tag...
- References: <F36bpH71yEXUIEAOeIi00000e6c@hotmail.com>
- Reply-to: xsl-list at lists dot mulberrytech dot com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Tuesday 18 June 2002 02:15, Anders Wasen wrote:
> I have looked into solving it with a script and deviding the string into
> peaces like rule/comment and then add text formating tags around the
> comment part(s), but the problem is that I don't know how many comments
> there is... this will only support one comment:
First, you are not using XSLT, you are using WD-XSL. The <xsl:eval> tag
doesn't exist in XSLT. Since I don't know WD-XSL, my attempted solution will
be in pure XSLT. Please feel free to disregard my suggestions, since you
will likely get better performance (but not portability) using an extension
function; if you wish to continue to use VBScript, you may do so. The
concept of the loop I describe can be adapted to any language, not just XSLT.
What you need is a loop: search for the leading "/*", output the text before
that "/*", output some formatting tags, search for the closing "*/", output
the text between the previous "/*" and that "*/", output some formatting
tags, and repeat. In XSLT, you can make such a loop with a recursive
template (since XSLT has no actual loop constructs), and the contains(),
substring-before(), and substring-after() functions will help.
The loop will need to alternate between two different states: (1) search for
the "/*", and (2) search for the "*/". When (1) is matched, the process will
proceed using (2), and once (2) is matched, the process will repeat with (1).
<!-- the 'xsl:' prefix has been removed from all elements for brevity -->
<template name="format-comment">
<param name="text"/>
<!-- state (1): search for the "/*" -->
<choose>
<when test="not(contains($text, '/*'))">
<!-- process complete; no more comments -->
<value-of select="$data"/>
</when>
<otherwise>
<!-- output text before the comment start -->
<value-of select="substring-before($text, '/*')"/>
<!-- ## output openning formatting tags ## -->
<text>/*</text>
<!-- search for closing '*/' -->
<call-template name="format-comment-close">
<!-- search in the remaining text following the '/*' -->
<with-param name="text" select="substring-after($text, '/*')"/>
</call-template>
</otherwise>
</choose>
</template>
<template name="format-comment-close">
<param name="text"/>
<!-- state (2) -->
<choose>
<when test="not(contains($text, '*/'))">
<!-- unclosed comment; it's up to you what to do here -->
<value-of select="$text"/>
</when>
<otherwise>
<!-- output text before the comment end -->
<value-of select="substring-before($text, '*/')"/>
<text>*/</text>
<!-- ## output closing formatting tags ## -->
<!-- repeat search for openning '/*' -->
<call-template name="format-comment">
<!-- search in the remaining text following the '*/' -->
<with-param name="text" select="substring-after($text, '*/')"/>
</call-template>
</otherwise>
</choose>
</template>
<!-- NOTE: THIS IS COMPLETELY UNTESTED -->
You may notice that the two templates share a lot of common structure; it
should be possible to collapse the two into a single template by doing some
tricks with <xsl:param/>, but I'll leave that up to you. For clarity (and to
save me time), I left it as two templates.
The biggest problem you will have with the above is with the HTML <div> tags
you want to output surrounding the comment. The openning "<div>" needs to be
output in the first template, but the closing "</div>" needs to be output in
the second template. This is not easy with XSLT.
I can think of two ways to work around this:
(1) Output the openning and closing <div></div> with disable-output-escaping
in order to avoid making the stylesheet well-formed XML:
<xsl:text disable-output-escaping="yes"><div ...></xsl:text>
<xsl:text disable-output-escaping="yes"></div></xsl:text>
(2) Nest multiple <div> tags, switching back and forth between normal and
"comment" formatting. I recommend this option solely because of the problems
inherent with d-o-e, but it can make the resulting HTML fairly ugly if the
text has a lot of comments (each comment and the text following the comment
will be nested successively deeper; the end of the text would be followed by
a series of "</div></div></div>...", one for each comment).
To do this, where I say "output openning formatting tags" in the first
template, you would surround the <call-template/> tag like this:
<div style="font-weight: bold; color: #494B95">
<xsl:call-template name="format-comment-close">
<xsl:with-param .../>
</xsl:call-template>
</div>
And you will surround the <call-template/> in the second template with another
<div> with "inverse" CSS properties:
<div style="font-weight: normal; color: #000000">
<xsl:call-template name="format-comment">
<xsl:with-param .../>
</xsl:call-template>
</div>
Hopefully it is clear how this will work when it is all put together. Hope
that helps!
- --
Peter Davis
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)
iD8DBQE9DwVONSZCJx7tYycRArZvAJ4yG5A3e4/K+xATGoQ7fYBQXOJqLACeKdvX
PDJr7lq26qNgcdEyehv4deg=
=DNED
-----END PGP SIGNATURE-----
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list