This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Format text within a XML tag...


-----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">&lt;div ...&gt;</xsl:text>
<xsl:text disable-output-escaping="yes">&lt;/div&gt;</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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]