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