RE: [xsl] Text markup for web forums, eg. [b]bold text[/b]

Subject: RE: [xsl] Text markup for web forums, eg. [b]bold text[/b]
From: "Daniel Joshua" <daniel.joshua@xxxxxxxxxxxx>
Date: Mon, 7 Jun 2004 11:08:34 +0800
David,

> if I am able to find the time to try to implement such a solution

Thanks for your reply. I appreciate this.


> Such a solution would probably create more confusion
> and set people back rather than forward in there understanding of the
> language.

Well, the use of XSL in this scenario is probably not a good idea.
However, this is my own project, and I decided that since I can
'hardcode' my logic to solve my problem, it should be ok.

Here's what I done, works (according to what I previously requested) as far
as I know.

Warning: This quite messy XSL...



  <xsl:template match="text">
    <div class="text">
      <xsl:call-template name="mark-up">
        <xsl:with-param name="content" select="value"/>
      </xsl:call-template>
    </div>
  </xsl:template>



  <xsl:template name="mark-up">
    <xsl:param name="content"/>

    <!-- pre-content -->
    <xsl:variable name="pre-content" select="substring-before($content,
'[')"/>
    <xsl:value-of select="$pre-content"/>

    <!-- tag-content -->
    <xsl:variable name="remaining-content" select="substring($content, 1 +
string-length($pre-content))"/>

    <xsl:choose>

      <!-- plain text -->
      <xsl:when test="not(contains($remaining-content, '['))">
        <xsl:value-of select="$content"/>
      </xsl:when>

      <!-- bold -->
      <xsl:when test="starts-with($remaining-content, '[b]')">
        <!-- find-tag-content -->
        <xsl:variable name="tag-content">
          <xsl:call-template name="find-tag-content">
            <xsl:with-param name="remaining-content"
select="substring-after($remaining-content, '[b]')"/>
            <xsl:with-param name="tag-to-find" select="'b'"/>
          </xsl:call-template>
        </xsl:variable>

        <xsl:choose>

          <!-- properly closed tag -->
          <xsl:when test="string-length($tag-content) &gt; 0">
            <b>
              <xsl:call-template name="mark-up">
                <xsl:with-param name="content" select="$tag-content"/>
              </xsl:call-template>
            </b>

            <!-- process the next tag -->
            <xsl:call-template name="mark-up">
              <xsl:with-param name="content"
select="substring-after($remaining-content, concat($tag-content, '[/b]'))"/>
            </xsl:call-template>
          </xsl:when>

          <!-- not a closed tag -->
          <xsl:otherwise>
            <xsl:text>[b]</xsl:text>

            <!-- process the next tag -->
            <xsl:call-template name="mark-up">
              <xsl:with-param name="content"
select="substring-after($remaining-content, '[b]')"/>
            </xsl:call-template>
          </xsl:otherwise>

        </xsl:choose>
      </xsl:when>

      <!-- italics -->
        <!-- the same as above -->

      <!-- quote -->

      <!-- img -->

      <!-- url (with no tag attribute) -->

      <!-- url (with url as tag attribute) -->

      <!-- email (with no tag attribute) -->

      <!-- email (with email as tag attribute) -->

      <!-- either not an opening tag or and invalid tag -->
      <xsl:otherwise>
        <xsl:variable name="bad-content"
select="concat(substring-before($remaining-content, '['), '[')"/>
        <xsl:value-of select="$bad-content"/>

        <!-- process the next tag -->
        <xsl:call-template name="mark-up">
          <xsl:with-param name="content"
select="substring($remaining-content, 1 + string-length($bad-content))"/>
        </xsl:call-template>
      </xsl:otherwise>

    </xsl:choose>

  </xsl:template>



  <xsl:template name="find-tag-content">
    <xsl:param name="remaining-content"/>
    <xsl:param name="tag-to-find"/>
    <xsl:param name="nesting-level" select="0"/>
    <xsl:param name="return-tag-content" select="''"/>

    <xsl:variable name="start-tag" select="concat('[', $tag-to-find, ']')"/>
    <xsl:variable name="end-tag" select="concat('[/', $tag-to-find, ']')"/>

    <xsl:variable name="content-before-next-start-tag"
select="substring-before($remaining-content, $start-tag)"/>
    <xsl:variable name="content-before-next-end-tag"
select="substring-before($remaining-content, $end-tag)"/>

    <xsl:variable name="length-before-next-start-tag"
select="string-length($content-before-next-start-tag)"/>
    <xsl:variable name="length-before-next-end-tag"
select="string-length($content-before-next-end-tag)"/>

    <xsl:if test="$length-before-next-end-tag &gt; 0">
      <!-- end tag found -->
      <xsl:choose>

        <!-- end tag is nearer the front -->
        <xsl:when test="$length-before-next-end-tag &lt;
$length-before-next-start-tag or $length-before-next-start-tag = 0">
          <xsl:choose>

            <!-- return tag contents -->
            <xsl:when test="$nesting-level = 0">
              <xsl:value-of select="concat($return-tag-content,
$content-before-next-end-tag)"/>
            </xsl:when>

            <!-- reduce nesting level, then recurse -->
            <xsl:otherwise>
              <xsl:call-template name="find-tag-content">
                <xsl:with-param name="remaining-content"
select="substring-after($remaining-content, $end-tag)"/>
                <xsl:with-param name="tag-to-find" select="$tag-to-find"/>
                <xsl:with-param name="nesting-level"
select="$nesting-level - 1"/>
                <xsl:with-param name="return-tag-content"
select="concat($return-tag-content, $content-before-next-end-tag,
$end-tag)"/>
              </xsl:call-template>
            </xsl:otherwise>

          </xsl:choose>
        </xsl:when>

        <!-- start tag is nearer the front -->
        <xsl:otherwise>
          <!-- increase nesting level, then recurse -->
          <xsl:call-template name="find-tag-content">
            <xsl:with-param name="remaining-content"
select="substring-after($remaining-content, $start-tag)"/>
            <xsl:with-param name="tag-to-find" select="$tag-to-find"/>
            <xsl:with-param name="nesting-level" select="$nesting-level +
1"/>
            <xsl:with-param name="return-tag-content"
select="concat($return-tag-content, $content-before-next-start-tag,
$start-tag)"/>
          </xsl:call-template>
        </xsl:otherwise>

      </xsl:choose>
    </xsl:if>
  </xsl:template>



I should be able to handle the rest (I am currently fixing a small bug when
there is no content within the 'markup'). However, feel free to comment on
any of the above.


Regards,
Daniel


-----Original Message-----
From: M. David Peterson [mailto:m.david@xxxxxxxxxx]
Sent: Saturday, 05 June, 2004 11:07 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Text markup for web forums, eg. [b]bold text[/b]


Sorry for the late reply to this message but it somehow got missed.  It only
got caught because I was trying to find another post from Wendell and saw
this when scanning his posts.

Wendell is right on target with all of this.  When I originally posted the
solution for converting the UBB markup I used a code base that I was
developing to act in a sort of search-and-replace type application and had
no intention of it being any sort of tree-style parser.  As such things like
recursion were not even considered.  Although I believe that this solution
could be modified to process the modified markup recursively that's only
because I love the challenge of making something work in a language it
wasn't
designed to work in and not because it's the right solution for the problem.
The final code-base of such an effort would probably look a lot like a bowl
of alphabet soup.  Sure, all the individual letters can be used to form
words but that doesn't mean that they do, or if they do, not in a way that
makes sense to anybody other than the person who put them there.  The
purpose of this list is to help others with there understanding of the
XSL-based languages.  Such a solution would probably create more confusion
and set people back rather than forward in there understanding of the
language.  As such this is definitely not the right place to be posting such
code.

Daniel,  if I am able to find the time to try to implement such a solution I
will contact you directly rather than risk confusing the general XSL public
with a bunch of psycho-babble nonsense that is likely to be the resulting
code-base.

Best regards,

<M:D/>

----- Original Message -----
From: "Wendell Piez" <wapiez@xxxxxxxxxxxxxxxx>
To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Tuesday, June 01, 2004 9:49 AM
Subject: Re: [xsl] Text markup for web forums, eg. [b]bold text[/b]


> At 06:31 AM 6/1/2004, George wrote:
> >How about translating also <> to [] in the first pass and apply in a
> >second pass a copy stylesheet with the output method set to xml this time
> >that will translate the [] back to <> ?
>
> George is being very cunning, but the bottom line here is that none of
> these approaches have yet proposed a good way of dealing with
> pseudo-markup
> that does not map directly to well-formed XML. And by definition, you have
> no intrinsic way of knowing that all the pseudo-markup you have, does map.
>
> (The reason you can't just change markup delimiters around in XSLT is that
> internally, the XSLT engine sees no markup; it has all been parsed away in
> the tree-building process.)
>
> Whether you work at the character level (translating back and forth
> between
> different markup delimiters) or try to implement a parser in XSLT (M.
> David's first approach) -- unless you have a generic solution for
> converting not-well-formed near-XML into true XML (and it won't be XSLT
> ;-), this isn't going to work outside controlled environments where you
> can
> either preclude badly-formed pseudo-markup altogether (in which case why
> not use real markup?), or where you can trap it and fix it when it turns
> up.
>
> Cheers,
> Wendell
>
> ><?xml version="1.0" encoding="UTF-8"?>
> ><text>
> ><value>Text may &lt; contain [b]bold text[/b], [i]italics[/i] or both
> >[b][i]bold and italics[/i][/b].</value>
> ></text>
>
>


Current Thread