RE: [xsl] RE: Next node name

Subject: RE: [xsl] RE: Next node name
From: "Casadome, Francisco Javier" <Francisco.Casadome@xxxxxxxxxxxxxx>
Date: Thu, 4 Apr 2002 17:50:44 +0200
Thanks a lot Jeni !

I'm going to keep improving the code and thinking on new possibilities.
The Replace template was really useful ! Never thought about it done that
way :/

Fran.

-----Original Message-----
From: Jeni Tennison [mailto:jeni@xxxxxxxxxxxxxxxx] 
Sent: Thursday, April 04, 2002 9:11 AM
To: Casadome, Francisco Javier
Cc: 'xsl-list@xxxxxxxxxxxxxxxxxxxxxx'
Subject: Re: [xsl] RE: Next node name


Hi Francisco,

> Here's the best solution I have found so far:

Your solution looks OK, although there's no need to bug out to VBScript to
do the replacing. You can just do:

<xsl:template name="Replace">
  <xsl:param name="str" />
  <xsl:param name="strout" />
  <xsl:param name="strin" />
  <xsl:choose>
    <xsl:when test="contains($str, $strout)">
      <xsl:value-of select="substring-before($str, $strout)" />
      <xsl:value-of select="$strin" />
      <xsl:value-of select="substring-after($str, $strout)" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

I found a solution that seems to work and is a bit less complicated. I
noticed that in all the examples, if you count the number of ut elements
before a piece of text and subtract from that the number of text nodes that
begin with &lt; and end with &gt;, then if you've got an even number then
you want to show the text while if you've got an odd number then you want to
replace the text with a (%VAR%).

So, this seems to work:

<xsl:template match="seg">
  <seg>
    <xsl:apply-templates mode="seg" />
  </seg>
</xsl:template>

<xsl:template match="ut" mode="seg" />

<xsl:template match="text()" mode="seg">
  <xsl:if test="not(starts-with(., '&lt;') and
                    substring(., string-length()) = '&gt;')">
    <xsl:variable name="previous-uts" select="count(preceding-sibling::ut)"
/>
    <xsl:variable name="previous-tags" 
      select="count(preceding-sibling::text()
                      [starts-with(., '&lt;') and
                       substring(., string-length()) = '&gt;'])" />
    <xsl:choose>
      <xsl:when test="($previous-uts + $previous-tags) mod 2">
        <xsl:text>(%VAR%)</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>    
  </xsl:if>
</xsl:template>

Another approach would be to step through the children of the seg element
one by one, keeping track of the number of ut and 'tag' text nodes as you
go. This is better if you've got long seg elements:

<xsl:template match="seg">
  <seg>
    <xsl:apply-templates select="node()[1]" mode="seg" />
  </seg>
</xsl:template>

<xsl:template match="ut" mode="seg">
  <xsl:param name="count" select="0" />
  <xsl:apply-templates select="following-sibling::node()[1]" mode="seg">
    <xsl:with-param name="count" select="$count + 1" />
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="text()" mode="seg">
  <xsl:param name="count" select="0" />
  <xsl:choose>
    <xsl:when test="starts-with(., '&lt;') and
                    substring(., string-length()) = '&gt;'">
      <xsl:apply-templates select="following-sibling::node()[1]" mode="seg">
        <xsl:with-param name="count" select="$count - 1" />
      </xsl:apply-templates>
    </xsl:when>
    <xsl:otherwise>
      <xsl:choose>
        <xsl:when test="$count mod 2">
          <xsl:text>(%VAR%)</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="." />
        </xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates select="following-sibling::node()[1]" mode="seg">
        <xsl:with-param name="count" select="$count" />
      </xsl:apply-templates>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

These solutions produce:

<seg>Click (%VAR%).</seg>
<seg>Click (%VAR%), and then click (%VAR%).</seg>

from the samples that you gave.

Note that neither of these will work if you've got segs that look
like:

  <seg>
    Click <ut>{\cs6\f1\cf6\lang1024</ut>&lt;img src="fig.gif"&gt;<ut>}</ut>
    ut>{\b </ut>Properties<ut>}</ut>.
  </seg>

Because the img start "tag" doesn't have an end tag, and will throw off the
counting. If that's going to be a problem, let me know and I'll look over
your solution in more detail to see if there's any room for improvement.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

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


Current Thread