The function normalize-space
removes leading and trailing whitespace and replaces sequences of whitespace characters by a single space. How can I only replaces sequences of whitespace characters by a single space in XSLT 1.0? For instance "..x.y...\n\t..z."
(spaces replaced by a dot for readability) should become ".x.y.z."
.
Asked
Active
Viewed 2,898 times
5

Dimitre Novatchev
- 240,661
- 26
- 293
- 431

Jakob
- 3,570
- 3
- 36
- 49
-
Good question, +1. See my answer for a one-liner XPath 1.0 expression -- solution (and of course, this is also an XSLT 1.0 solution, too). :) No extension functions needed/used. – Dimitre Novatchev Feb 18 '11 at 05:30
-
Check my answer for a three function calls solution. – Feb 18 '11 at 17:44
2 Answers
7
Use this XPath 1.0 expression:
concat(substring(' ', 1 + not(substring(.,1,1)=' ')),
normalize-space(),
substring(' ', 1 + not(substring(., string-length(.)) = ' '))
)
To verify this, the following transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select=
"concat(substring(' ', 1 + not(substring(.,1,1)=' ')),
normalize-space(),
substring(' ', 1 + not(substring(., string-length(.)) = ' '))
)
"/>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document:
<t>
<t1> xxx yyy zzz </t1>
<t2>xxx yyy zzz</t2>
<t3> xxx yyy zzz</t3>
<t4>xxx yyy zzz </t4>
</t>
produces the wanted, correct result:
<t>
<t1> xxx yyy zzz </t1>
<t2>xxx yyy zzz</t2>
<t3> xxx yyy zzz</t3>
<t4>xxx yyy zzz </t4>
</t>

Dimitre Novatchev
- 240,661
- 26
- 293
- 431
-
Thanks! I'll use Alejandro's method although it relies of data that does not contain a special character. Both answers are helpful :-) – Jakob Feb 20 '11 at 17:50
-
@Jacob: You are welcome. I guess that you chose @Alejandro's answer because he split the expression into variables and thus made it more understandable. You may be aware that among ourselves we pride in providing one-liner XPath solutions :) – Dimitre Novatchev Feb 20 '11 at 19:53
-
I must admit that in doubt I choose the answer from the user with less reputation (if there are multiple equal answers), just to narrow the gap ;-) XPath is great. If only XSLT would have a more readable syntax, similar to XPath!! – Jakob Feb 20 '11 at 23:47
-
@Jacob: In XSLT 2.0 one can code almost completely in XPath 2.0 - only. Even better in XSLT 3.0. – Dimitre Novatchev Feb 20 '11 at 23:57
2
Without Becker's method, you could use some discouraged character as mark:
translate(normalize-space(concat('',.,'')),'','')
Note: Three function calls...
Or with any character but repeating some expression:
substring(
normalize-space(concat('.',.,'.')),
2,
string-length(normalize-space(concat('.',.,'.'))) - 2
)
In XSLT you can easily declare a variable:
<xsl:variable name="vNormalize" select="normalize-space(concat('.',.,'.'))"/>
<xsl:value-of select="susbtring($vNormalize,2,string-length($vNormalize)-2)"/>
-
Thanks, the use of discouraged characters is a clever trick. You only forgot the `;` after each character entity (or it got lost when editing). – Jakob Feb 20 '11 at 17:48
-
@Jakob: You are welcome. Also you are correct: I've forgotten last `;` in entities. Sorry. – Feb 20 '11 at 21:44