How can I trim space in XSLT without replacing rep

2019-01-19 11:20发布

The function normalize-space replaces sequences of whitespaces by a single space and trims the provided string. How can I only trim the string without the replacement of whitespaces? There are proprietary solutions like orcl:left-trim, but I am looking for a non-proprietary one.

Example:

<xsl:value-of select="trim(/Car/Description)"/>

should turn

<car>
  <description>  To get more information look at:     www.example.com </description>
</car>

into

"To get more information look at:     www.example.com"

标签: xml xslt xpath
5条回答
戒情不戒烟
2楼-- · 2019-01-19 11:45

A solution using just xslt 1.0 templates:

<xsl:variable name="whitespace" select="'&#09;&#10;&#13; '" />

<!-- Strips trailing whitespace characters from 'string' -->
<xsl:template name="string-rtrim">
    <xsl:param name="string" />
    <xsl:param name="trim" select="$whitespace" />

    <xsl:variable name="length" select="string-length($string)" />

    <xsl:if test="$length &gt; 0">
        <xsl:choose>
            <xsl:when test="contains($trim, substring($string, $length, 1))">
                <xsl:call-template name="string-rtrim">
                    <xsl:with-param name="string" select="substring($string, 1, $length - 1)" />
                    <xsl:with-param name="trim"   select="$trim" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$string" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:if>
</xsl:template>

<!-- Strips leading whitespace characters from 'string' -->
<xsl:template name="string-ltrim">
    <xsl:param name="string" />
    <xsl:param name="trim" select="$whitespace" />

    <xsl:if test="string-length($string) &gt; 0">
        <xsl:choose>
            <xsl:when test="contains($trim, substring($string, 1, 1))">
                <xsl:call-template name="string-ltrim">
                    <xsl:with-param name="string" select="substring($string, 2)" />
                    <xsl:with-param name="trim"   select="$trim" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$string" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:if>
</xsl:template>

<!-- Strips leading and trailing whitespace characters from 'string' -->
<xsl:template name="string-trim">
    <xsl:param name="string" />
    <xsl:param name="trim" select="$whitespace" />
    <xsl:call-template name="string-rtrim">
        <xsl:with-param name="string">
            <xsl:call-template name="string-ltrim">
                <xsl:with-param name="string" select="$string" />
                <xsl:with-param name="trim"   select="$trim" />
            </xsl:call-template>
        </xsl:with-param>
        <xsl:with-param name="trim"   select="$trim" />
    </xsl:call-template>
</xsl:template>

Test code:

<ltrim>
    <xsl:call-template name="string-ltrim">
        <xsl:with-param name="string" select="'   &#10;   test  '" />
    </xsl:call-template>
</ltrim>
<rtrim>
    <xsl:call-template name="string-rtrim">
        <xsl:with-param name="string" select="'    &#10;    test  &#10;  '" />
    </xsl:call-template>
</rtrim>
<trim>
    <xsl:call-template name="string-trim">
        <xsl:with-param name="string" select="'    &#10;    test  &#10;  '" />
    </xsl:call-template>
</trim>

Output:

<test>
    <ltrim>test  </ltrim>
    <rtrim>   
    test</rtrim>
    <trim>test</trim>
</test>
查看更多
啃猪蹄的小仙女
3楼-- · 2019-01-19 11:51

A very short solution with XSLT1:

<xsl:template name="trim">
            <xsl:param name="str"/>

            <xsl:choose>
                <xsl:when test="string-length($str) &gt; 0 and substring($str, 1, 1) = ' '">
                    <xsl:call-template name="trim"><xsl:with-param name="str"><xsl:value-of select="substring($str, 2)"/></xsl:with-param></xsl:call-template></xsl:when>
                <xsl:when test="string-length($str) &gt; 0 and substring($str, string-length($str)) = ' '">
                    <xsl:call-template name="trim"><xsl:with-param name="str"><xsl:value-of select="substring($str, 1, string-length($str)-1)"/></xsl:with-param></xsl:call-template></xsl:when>
                <xsl:otherwise><xsl:value-of select="$str"/></xsl:otherwise>
            </xsl:choose>
        </xsl:template>
查看更多
霸刀☆藐视天下
4楼-- · 2019-01-19 11:53

Using FXSL (open source library for XSLT functional programming, written entirely in XSLT) one simply writes:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="trim.xsl"/>

  <xsl:output method="text"/>
  <xsl:template match="/*/description">
    '<xsl:call-template name="trim">
        <xsl:with-param name="pStr" select="."/>
    </xsl:call-template>'
  </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<car>
  <description>  To get more information look at:     www.example.com </description>
</car>

the wanted, correct result is produced:

'To get more information look at:     www.example.com'

How does the trim template work?

It trims the left leading whitespace, then it reverses the resulting string and trims its leading whitespace, then it finally reverses the resulting string.


II. XPath 2.0 solution:

Use:

replace(replace(/*/description, '^\s*(.+?)\s*$', '$1'), '^ .*$', '')

Here is an XSLT - 2.0 - based verification:

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
     "<xsl:sequence 
      select="replace(replace(/*/description, '^\s*(.+?)\s*$', '$1'), '^ .*$', '')"/>"
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document (above), the XPath expression is evaluated and the result of this evaluation is copied to the output:

 "To get more information look at:     www.example.com"
查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-19 12:03

normalize-space(actualSting) - This will do it.

查看更多
可以哭但决不认输i
6楼-- · 2019-01-19 12:09

If you don't have any spaces in the middle, you can simply use:

translate(/Car/Description,' ','')
查看更多
登录 后发表回答