Re: [xsl] For-each adds whitespace per iteration: why?

Subject: Re: [xsl] For-each adds whitespace per iteration: why?
From: Eliot Kimber <ekimber@xxxxxxxxxx>
Date: Fri, 10 Jan 2014 12:59:44 -0600
Ah, that explains it. I have gotten in the habit of preferring
+ADw-xsl:sequence+AD4- over +ADw-xsl:value-of+AD4- but this is apparently one
place where
I should not have.

A subtle aspect of the spec.

I+IBk-m glad my understanding of +IBw-concatenation+IB0- in this context was
incorrect.

The key bit from 5.7.1 appears to step 3 of the sequence processing rules:

+ACI-3. Any consecutive sequence of strings within the result sequence is
converted to a single text node, whose string value
+ADw-http://www.w3.org/TR/xslt20/+ACM-dt-string-value+AD4- contains the
content of
each of the strings in turn, with a single space (+ACM-x20) used as a
separator between successive strings.+ACI-

That makes things clear.

Cheers,

Eliot


--
Eliot Kimber
Senior Solutions Architect
+ACI-Bringing Strategy, Content, and Technology Together+ACI-
Main: 512.554.9368
www.reallysi.com
www.rsuitecms.com




On 1/10/14, 11:27 AM, +ACI-Michael Kay+ACI- +ADw-mike+AEA-saxonica.com+AD4-
wrote:

+AD4-
+AD4-On 10 Jan 2014, at 17:05, Eliot Kimber +ADw-ekimber+AEA-rsicms.com+AD4-
wrote:
+AD4-
+AD4APg- In the context of writing an XSLT to generate DTD syntax from RNGs
(for
+AD4APg- DITA 1.3) I discovered that for-each results in whitespace being
emitted
+AD4APg- for each iteration. This came as a surprise. Reading the spec it
says,
+AD4APg- under clause 7, Repetition:
+AD4APg-
+AD4APg- +ACI-For each item in the input sequence, evaluating the sequence
+AD4APg-constructor
+AD4APg- +ADw-http://www.w3.org/TR/xslt20/+ACM-dt-sequence-constructor+AD4-
produces a
+AD4APg-sequence
+AD4APg- of items (see 5.7 Sequence Constructors
+AD4APg- +ADw-http://www.w3.org/TR/xslt20/+ACM-sequence-constructors+AD4-).
These output
+AD4APg- sequences are concatenated+ADs- ...
+AD4APg-
+AD4APg- I understand +ACI-These output sequences are concatenated+IB0- to
mean that
+AD4APg-string
+AD4APg- concatenation rules are applied, which explains the white space.
+AD4-
+AD4-No, this is a concatenation of two or more sequences to produce a single
+AD4-sequence. No whitespace is added at this point.
+AD4-
+AD4APg-
+AD4APg- My question: why is for-each defined in this way?
+AD4-
+AD4-It isn't.
+AD4APg-
+AD4APg-
+AD4APg- I tested this with this little XSLT transform:
+AD4APg-
+AD4APg- +ADw-?xml version+AD0AIg-1.0+ACI- encoding+AD0AIg-UTF-8+ACI-?+AD4-
+AD4APg- +ADw-xsl:stylesheet
xmlns:xsl+AD0AIg-http://www.w3.org/1999/XSL/Transform+ACI-
+AD4APg-  xmlns:xs+AD0AIg-http://www.w3.org/2001/XMLSchema+ACI-
+AD4APg-  xmlns:xd+AD0AIg-http://www.oxygenxml.com/ns/doc/xsl+ACI-
+AD4APg-  exclude-result-prefixes+AD0AIg-xs xd+ACI-
+AD4APg-  version+AD0AIg-2.0+ACIAPg-
+AD4APg-
+AD4APg-  +ADw-xsl:output method+AD0AIg-text+ACI-/+AD4-
+AD4APg-
+AD4APg-  +ADw-xsl:template name+AD0AIg-test-for-each+ACIAPg-
+AD4APg-    +ADw-xsl:variable name+AD0AIg-strings+ACI- select+AD0AIg-('one',
'two', 'three',
+AD4APg-'four')+ACI-/+AD4-
+AD4APg- value-of +ACQ-strings+AD0APA-xsl:value-of
select+AD0AIgAk-strings+ACI-/+AD4-
+AD4APg- for +ACQ-str in +ACQ-strings return concat('/', +ACQ-str,
'/')+AD0APA-xsl:sequence
+AD4APg- select+AD0AIg-for +ACQ-str in +ACQ-strings return concat('/',
+ACQ-str, '/')+ACI-/+AD4-
+AD4APg- string-join(+ACQ-strings, '')+AD0APA-xsl:sequence
select+AD0AIg-string-join(+ACQ-strings,
+AD4APg- '')+ACI-/+AD4-
+AD4APg- for-each over strings: +ACIAPA-xsl:for-each
select+AD0AIgAk-strings+ACIAPg-
+AD4APg-  +ADw-xsl:sequence select+AD0AIg-concat('/',.,'/')+ACI-/+AD4-
+AD4APg- +ADw-/xsl:for-each+AD4AIg-
+AD4APg-  +ADw-/xsl:template+AD4-
+AD4APg-
+AD4APg- +ADw-/xsl:stylesheet+AD4-
+AD4APg-
+AD4APg-
+AD4APg-
+AD4APg- Which produces this output using Saxon 9.5.1.2:
+AD4APg-
+AD4APg- value-of +ACQ-strings+AD0-one two three four
+AD4APg- for +ACQ-str in +ACQ-strings return concat('/', +ACQ-str,
'/')+AD0-/one/ /two/ /three/
+AD4APg- /four/
+AD4APg- string-join(+ACQ-strings, '')+AD0-onetwothreefour
+AD4APg- for-each over strings: +ACI-/one/ /two/ /three/ /four/+ACI-
+AD4APg-
+AD4-The whitespace is being added as part of the process of constructing
your
+AD4-final result tree from a sequence of strings. The result tree is
+AD4-constructed as a document node, following the rules of 5.7.1
Constructing
+AD4-Complex Content
+AD4-
+AD4-http://www.w3.org/TR/2009/PER-xslt20-20090421/+ACM-constructing-complex-
conten
+AD4-t
+AD4-
+AD4-or equivalently the rules applied by the Serializer
+AD4-
+AD4-http://www.w3.org/TR/xslt-xquery-serialization/+ACM-serdm
+AD4-
+AD4-The simplest way to avoid the space separation is to construct text
nodes
+AD4-rather than strings, which happens if you replace xsl+ADs-sequence by
+AD4-xsl:value-of in
+AD4-
+AD4APg- +ADw-xsl:sequence select+AD0AIg-concat('/',.,'/')+ACI-/+AD4-
+AD4-
+AD4-Michael Kay
+AD4-Saxonica
+AD4-
+AD4APg-
+AD4APg- I see that the for-each result is consistent with the flowr
expression.
+AD4APg-
+AD4APg- Is my analysis correct that the only way to construct a string with
no
+AD4APg- extra whitespace using a loop is to use string-join() as in my test
+AD4APg-case?
+AD4APg-
+AD4APg- For my DTD-generation application that would mean using the for-each
+AD4APg-loop
+AD4APg- to construct a sequence of strings and then using string-join on the
+AD4APg- sequence to avoid additional whitespace. Of course I can simply
account
+AD4APg- for the space inserted by the concatenation and get the correct
+AD4APg-indention
+AD4APg- and keep my code a bit simpler.
+AD4APg-
+AD4APg- Cheers,
+AD4APg-
+AD4APg- Eliot
+AD4APg-
+AD4APg- --
+AD4APg- Eliot Kimber
+AD4APg- Senior Solutions Architect
+AD4APg- +ACI-Bringing Strategy, Content, and Technology Together+ACI-
+AD4APg- Main: 512.554.9368
+AD4APg- www.reallysi.com
+AD4APg- www.rsuitecms.com
+AD4APg-
+AD4APg-
+AD4APg-
+AD4APg-
--+//0-------------------------------------------------------------------
+AD4APg- XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
+AD4APg- To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
+AD4APg- or e-mail:
+ADw-mailto:xsl-list-unsubscribe+AEA-lists.mulberrytech.com+AD4-
+AD4APg- --+//0---
+AD4APg-
+AD4-
+AD4-
+AD4---+AH4------------------------------------------------------------------
-
+AD4-XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
+AD4-To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
+AD4-or e-mail:
+ADw-mailto:xsl-list-unsubscribe+AEA-lists.mulberrytech.com+AD4-
+AD4---+AH4---
+AD4-

Current Thread