This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: String parsing in XSLT/XPath?


Hi Ying,

> I need to transform an XML doc to an HTML doc. There is one element
> that contains multiple lines and will need to be shown in the HTML
> doc as multiple lines as well. Bascially I will need to put <BR/> to
> the end of each line of that element.

You need to use a recursive template to search and replace within the
string. Here is one:

<xsl:template match="node()" mode="replaceLineBreaks"
              name="replaceLineBreaks">
  <xsl:param name="string" select="." />
  <xsl:choose>
    <!-- if the string contains a line break... -->
    <xsl:when test="contains($string, '&#xA;')">
      <!-- give the part before the line break... -->
      <xsl:value-of select="substring-before($string, '&#xA;')" />
      <!-- then a br element... -->
      <br />
      <!-- and then call the template recursively on the rest of the
           string -->
      <xsl:call-template name="replaceLineBreaks">
        <xsl:with-param name="string"
                        select="substring-after($string, '&#xA;')" />
      </xsl:call-template>
    </xsl:when>
    <!-- if the string doesn't contain a line break, just give its
         value, followed by a br element -->
    <xsl:otherwise>
      <xsl:value-of select="$string" /><br />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

You can apply this template to the ADDRESS element with:

  <xsl:apply-templates select="ADDRESS" mode="replaceLineBreaks" />

I doubt this is relevant, since you're dealing with addresses, which
tend to be fairly short, but if you're dealing with long strings with
lots of line breaks in them, then you may find it more efficient to
use a divide-and-conquer approach whereby you split the remaining
string. This has the advantage of limiting the depth of the recursion,
and therefore the call stack, but the disadvantage of not being tail
recursive and therefore not amenable to optimisation:

<xsl:template match="node()" mode="replaceLineBreaks"
              name="replaceLineBreaks">
  <xsl:param name="string" select="." />
  <xsl:choose>
    <!-- if the string contains a line break... -->
    <xsl:when test="contains($string, '&#xA;')">
      <!-- give the part before the line break... -->
      <xsl:value-of select="substring-before($string, '&#xA;')" />
      <!-- then a br element... -->
      <br />
      <!-- and then call the template recursively on the rest of the
           string, splitting it into two to limit the depth of the
           recursion -->
      <xsl:variable name="remainingString"
                    select="substring-after($string, '&#xA;')" />
      <xsl:variable name="halfRemainingStringLength"
         select="floor(string-length($remainingString) div 2)" />
      <xsl:call-template name="replaceLineBreaks">
        <xsl:with-param name="string"
                        select="substring($remainingString, 1,
                                          $halfRemainingStringLength)" />
      </xsl:call-template>
      <xsl:call-template name="replaceLineBreaks">
        <xsl:with-param name="string"
           select="substring($remainingString,
                             $halfRemainingStringLength + 1)" />
      </xsl:call-template>
    </xsl:when>
    <!-- if the string doesn't contain a line break, just give its
         value -->
    <xsl:otherwise>
      <xsl:value-of select="$string" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

With this, you will have to add the <br /> to the end of the string
yourself.

If performance is an issue, I suggest that you try both of the
templates on your particular data and processor to see which is best
for you; if neither is significantly faster than the other, then use
the one you feel most comfortable with maintaining.

I hope that helps,

Jeni

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]