Re: [xsl] RE: Next node name

Subject: Re: [xsl] RE: Next node name
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Thu, 4 Apr 2002 08:10:59 +0100
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