user3402743
user3402743

Reputation: 593

In XSLT, how do I truncate a value to the first five characters?

So, I know absolutely nothing about XSLT. I don't know what I'm doing, I don't know what I'm supposed to make the code do, and I don't know how to make it do whatever it is supposed to do.

That being said, I know I'm supposed to truncate a name to the first five characters.

I have this:

<xsl:if test="string-length(/myQuery/Arguments/FirstName) &gt;= 6">
<xsl:variable name = "x" select = "substring(/myQuery/Arguments/FirstName, 1, 5)"/>
</xsl:if>

So, that does assign a truncated version of FirstName to X. But how do I get it back into FirstName?

Upvotes: 0

Views: 17323

Answers (2)

John Bollinger
John Bollinger

Reputation: 180998

You haven't given us much to work with, but let's begin with this: an XSLT processor doesn't modify anything. Rather it takes an XML input and produces a transformed version (which is not necessarily XML).

Reverse-engineering your XSL leads me to believe that your input document could look something like this:

<?xml version="1.0"?>
<myQuery>
  <Arguments>
    <FirstName>Jonathon</FirstName>
  </Arguments>
</myQuery>

If the objective is to produce a document that is the same, except for truncating the text in the <FirstName> element, then that might look like this:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- by default, transform every node and attribute into a copy of itself -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Where needed, transform FirstName elements with truncation -->
  <xsl:template match="/myQuery/Arguments/FirstName[string-length(.) &gt; 5]">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:value-of select="substring(., 1, 5)" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Transforming the example input above via that stylesheet yields

<?xml version="1.0"?>
<myQuery>
<Arguments>
<FirstName>Jonat</FirstName>
</Arguments>
</myQuery>

Points to note:

  • <xsl:template> elements define how different parts of the input document are transformed. Document parts are selected via XPath expressions; the transformation is expressed by the body of the template.
  • Where you want to produce a transformed document that has only small differences from the original, it greatly simplifies things to use an identity transform, such as the one appearing first in the above stylesheet.
  • At most one template will selected for transforming any given node in the input document. When more than one matches a given node, there are priority rules for choosing which one is used. Pretty much anything has priority over the selector in the given identity transform, and where the priority is the same, the template appearing last in the stylesheet is chosen.

There's much more to XSLT, but I hope that gets you going.

Upvotes: 1

Daniel Haley
Daniel Haley

Reputation: 52878

Use an identity transform and then override what you're trying to change...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="FirstName[string-length(normalize-space())>=6]/text()">
        <xsl:value-of select="substring(normalize-space(),1,5)"/>
    </xsl:template>

</xsl:stylesheet>

Upvotes: 2

Related Questions