开发者

How to show a character n times in XSLT?

I have a template with a parameter. H开发者_JAVA百科ow can I insert a tab character n times?

n is the value of the parameter.


In XSLT 2.0:

<xsl:for-each select="1 to $count">&#x9;</xsl:for-each>

(Sadly though, I suspect that if you were using XSLT 2.0 you wouldn't need to ask the question).

Another technique often used with XSLT 1.0 is the hack:

<xsl:for-each select="//*[position() &lt;= $count]">&#x9;</xsl:for-each>

which works provided the number of elements in your source document is greater than the number of tab characters you want to output.


Just call it recursively; output a tab, then call the same template again with n-1 passed in, if n > 1.

<xsl:template name="repeat">
  <xsl:param name="output" />
  <xsl:param name="count" />
  <xsl:if test="$count &gt; 0">
    <xsl:value-of select="$output" />
    <xsl:call-template name="repeat">
      <xsl:with-param name="output" select="$output" />
      <xsl:with-param name="count" select="$count - 1" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

As has been pointed out, this example will actually output a minimum of one. In my experience where the output is whitespace, it's usually needed. You can adapt the principle of a recursive template like this any way you see fit.


Globally define a long enough array of tabs:

<xsl:variable name="TABS" select="'&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;'" />

Then use like this:

<xsl:value-of select="fn:substring($TABS, 1, fn:number($COUNT))" />


This seems the simplest and most flexible to me.

For XSLT 1.0 (or perhaps 1.1).

<xsl:variable name="count">10</xsl:variable>
<xsl:variable name="repeat"><xsl:text>&#9;</xsl:text></xsl:variable>
<xsl:sequence select="string-join((for $i in 1 to $count return $repeat),'')"/>

Of course the count variable is where you assign your n parameter.

I used the variable repeat to hold the tab character, but you could just replace the $repeat with the tab character in single quotes in the sequence element. Note: This variable can be of a length greater than 1, which creates a whole bunch of possibilities.

It does not use recursion, so it won't run into a recursion limit.

I don't know the maximum value you can use for count, but I tested it up to 10,000.


(XSLT 1.0)

<xsl:template name="tabs">
    <xsl:param name="n"/>

    <xsl:if test="$n > 0">                              <!-- When n = 0, output nothing.           -->
        <xsl:call-template name="tabs">                 <!-- Recursive call: call same template... -->
            <xsl:with-param name="n" select="$n - 1"/>  <!-- ... for writing n - 1 tabs.           -->
        </xsl:call-template>
        <xsl:text>&#x9;</xsl:text>                      <!-- Add one tab character.                -->
    </xsl:if>

</xsl:template>

Example usage:

<xsl:call-template name="tabs">
   <xsl:with-param name="n" select="3"/>
</xsl:call-template>


I've discovered an LGPL-licensed library for doing this called functx, as I was sure someone had to have already done this... This is a "standard library" type XSLT library, which contains a function called repeat-string. From the docs:

The functx:repeat-string function returns a string consisting of a given number of copies of $stringToRepeat concatenated together.

Where I use it like this in my code:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:functx="http://www.functx.com">
  <xsl:import href="../buildlib/functx-1.0.xsl"/>

  <xsl:output omit-xml-declaration="yes" />

  <xsl:variable name="INDENT" select="'   '" />
    ....
  <xsl:template match="node()|@*">
      <xsl:copy>
          <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
  </xsl:template>

      <xsl:template match="data-pusher-properties">
          <xsl:for-each select="property">
              <xsl:choose>
                  ...
                  <xsl:when test="boolean(@value = '${pusher.notifications.server}')">
                      <xsl:value-of select="functx:repeat-string($INDENT, @indent)" />
                      <xsl:text>&quot;</xsl:text>
                      <xsl:value-of select="@name" />
                      <xsl:text>&quot;: </xsl:text>
                      <xsl:text>&quot;</xsl:text>
                      <xsl:value-of select="$pusher.notifications.email.server" />
                      <xsl:text>&quot;\&#xA;</xsl:text>
                  </xsl:when>
                  ...
              </xsl:choose>
          </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>

So for printing a tab character n times, call it like this:

<xsl:value-of select="functx:repeat-string('&#x9;', n)" />

I know this question is old, but I hope this can still help someone.

Documentation for the repeat-string function

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜