3

I have a function that adds a zero-width characters. It's not quite working the way I want it to though. How do I get it to add the zero-space character every 15 chars only if it does not contain a normal space?

<xsl:template match="text()[parent::d:entry]">
    <xsl:call-template name="intersperse-with-zero-spaces">
        <xsl:with-param name="str" select="."/>
        <xsl:with-param name="max_length" select="number(15)"/>
    </xsl:call-template>
</xsl:template>
<xsl:template name="intersperse-with-zero-spaces">
        <xsl:param name="str"/>
        <xsl:param name="max_length"/>
        <xsl:variable name="ret">
            <xsl:value-of select="substring($str, 1, $max_length)"/>
            <xsl:if test="string-length($str) &gt; $max_length">
                <xsl:value-of select="'&#x200b;'"/>
                <xsl:call-template name="intersperse-with-zero-spaces">
                    <xsl:with-param name="str" select="substring($str, $max_length + 1)"/>
                    <xsl:with-param name="max_length" select="$max_length"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:variable>
        <xsl:value-of select="$ret"/>
    </xsl:template>
Ace
  • 821
  • 3
  • 16
  • 37

1 Answers1

3

A few hints. First off:

<xsl:template match="d:entry/text()">

is better than

<xsl:template match="text()[parent::d:entry]">

And then:

<xsl:template name="intersperse-with-zero-spaces">
  <xsl:param name="str"/>
  <xsl:param name="max_length"/>

  <!-- your variable "ret" is not necessary at all -->

  <xsl:variable name="head" select="substring($str, 1, $max_length)" />
  <xsl:variable name="tail" select="substring($str, $max_length + 1)" />

  <xsl:value-of select="$head"/>

  <!-- the empty string evaluates to false -->
  <xsl:if test="$tail">
    <!-- there's no space present when translate() returns the same string
         and the $tail does not begin with a space, either  -->
    <xsl:if test="
      string-length(translate($head, ' ', '')) = string-length($head)
      and not(substring($tail, 1, 1) = ' ')
    ">
      <xsl:text>&#x200b;</xsl:text>
    </xsl:if>
    <xsl:call-template name="intersperse-with-zero-spaces">
      <xsl:with-param name="str"        select="$tail"/>
      <xsl:with-param name="max_length" select="$max_length"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

Also, I'd probably call the variable $interval, not $max_length. But that's purely cosmetic.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • @Tomalak: Not quite. Your checking for the space only between the substrings. I don't want a zero-space character added at all if the substrings contain **any** space character – Ace Jan 12 '11 at 19:20
  • @Ace: I did not understand the question that way. But that's easy. compare `string-length($str)` to `string-length(translate($str, ' ', ''))`. If they are equal, then `$str` does not contain spaces. – Tomalak Jan 12 '11 at 19:22
  • @Tomalak: No problem, I'll update my question to make it more clear, could you update your answer? – Ace Jan 12 '11 at 19:31
  • @Ace: Done. I guess you want to enable line-breaks in very long words? – Tomalak Jan 12 '11 at 19:43