This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: A better way to build a comma-delimited list


While reading Tom's answer I hope the last lights are switched on in my 
head. It takes very long today ...

 > <xsl:text>select </xsl:text>
 > <xsl:variable name="string">
 >    <xsl:for-each select="document($pbsdef)/pbsdef/column
 >              [not(@dbcolumn=preceding-sibling::column/@dbcolumn)]">
 >       <xsl:variable name="p" select="position()"/>
 >       <xsl:variable name="dbcolumn" select="@dbcolumn"/>
 >       <xsl:for-each select="$dbdef[key('dbdef-cols', $dbcolumn)]">
 >          <xsl:text>, </xsl:text>
 >          <xsl:value-of select="$dbcolumn"/>
 >       </xsl:for-each>
 >    </xsl:for-each>
 > </xsl:variable>
 > <xsl:value-of select="substring($string, 2)"/>

It's only a bit easier than Tom's solution, because you don't need the 
string-length.

Joerg


Joerg Heinicke wrote:
> Oh sorry. Your mail switched some lights on ;-)
> 
> I remember that for-each $dbdef was only for switching into the other 
> document, wasn't it? Then your solution using $p and $l was absolutely 
> correct (in theory). But the problem will still be there. The problem is 
> that the nodeset from the outer for-each (which the last() refers too) 
> is not the output, because of a further condition (the inner for-each). 
> It's really tricky then. If not anybody else has a better solution a 
> recursive approach or at least a step-by-step approach (using 
> following-sibling::*[1]) can be necessary. The following is not using 
> last(), but testing for the first element. It has the same weak point as 
> the other one, but maybe works with your code (the first @dbcolumn must 
> be in $dbdef). Another possibility
> is using a variable, which stores the string and a recursive template 
> which removes all leading commas. Hmm, when writing this a got a new 
> idea. When you don't add a comma, but a space before or after a column, 
> you can do a normalize-space on the variable and replace every space 
> with a comma after this:
> 
> <xsl:text>select </xsl:text>
> <xsl:variable name="string">
>    <xsl:for-each 
> select="document($pbsdef)/pbsdef/column[not(@dbcolumn=preceding-sibling::column/@dbcolumn)]"> 
> 
>       <xsl:variable name="p" select="position()"/>
>       <xsl:variable name="dbcolumn" select="@dbcolumn"/>
>       <xsl:for-each select="$dbdef[key('dbdef-cols', $dbcolumn)]">
>          <xsl:if test="$p != 1">
>             <xsl:text> </xsl:text>
>          </xsl:if>
>          <xsl:value-of select="$dbcolumn"/>
>       </xsl:for-each>
>    </xsl:for-each>
> </xsl:variable>
> <xsl:value-of select="translate(normalize-space($string), ' ', '')"/>
> 
> This should result in "select col1,col2,col3".
> 
> Regards,
> 
> Joerg
> 
> John Sands wrote:
> 
>> Hi Joerg,
>>
>>
>>> <xsl:for-each select="$dbdef[key('dbdef-cols', $dbcolumn)]">
>>>   <xsl:value-of select="$dbcolumn"/>
>>>   <xsl:if test="position() != last()">
>>>     <xsl:text>, </xsl:text>
>>>   </xsl:if>
>>> </xsl:for-each>
>>
>>
>>
>> I loved the solution because it would fix the problem AND make the
>> code shorter. Unfortunately it doesn't work because position() and
>> last() are both 1 so I get:
>>
>>  select col1col2col3
>>
>> John
>>
>>
>>
>>
>>
>>> -----Original Message-----
>>> From: Joerg Heinicke  <joerg.heinicke@gmx.de>
>>> Sent: Wednesday, May 15, 2002, 3:15:02 AM,
>>> Subject: [xsl] A better way to build a comma-delimited list
>>
>>
>>
>>> Hello John,
>>
>>
>>
>>> >       <xsl:for-each select="$dbdef">
>>> >          <xsl:if test="key('dbdef-cols', $dbcolumn)">
>>> >             <xsl:value-of select="$dbcolumn"/>
>>> >             <xsl:if test="$p &lt; $l">
>>> >                <xsl:text>, </xsl:text>
>>> >             </xsl:if>
>>> >          </xsl:if>
>>> >       </xsl:for-each>
>>
>>
>>
>>> instead of the for-each + if you can write one for-each with predicate:
>>
>>
>>
>>> <xsl:for-each select="$dbdef[key('dbdef-cols', $dbcolumn)]">
>>
>>
>>
>>> Now the correct nodeset is selected and position() and last() will 
>>> work. But they must refer to the inner for-each, so you can't use $p 
>>> and $l, but <xsl:if test="position() != last()">.
>>
>>
>>
>>> So, you have then
>>
>>
>>
>>> <xsl:for-each select="$dbdef[key('dbdef-cols', $dbcolumn)]">
>>>   <xsl:value-of select="$dbcolumn"/>
>>>   <xsl:if test="position() != last()">
>>>     <xsl:text>, </xsl:text>
>>>   </xsl:if>
>>> </xsl:for-each>
>>
>>
>>
>>> Regards,
>>
>>
>>
>>> Joerg
>>
>>
>>
>>> John Sands schrieb:
>>>
>>>> I have some XSLT that builds a SQL select statement from several input
>>>> documents. Here's a fragment that builds the column list by getting
>>>> each distinct column name from a separate file ($pbsdef) and checking
>>>> that is is defined in another file (referenced by variable $dbdef).
>>>>
>>>>   <xsl:text>select </xsl:text>
>>>>   <xsl:for-each 
>>>> select="document($pbsdef)/pbsdef/column[not(@dbcolumn=preceding-sibling::column/@dbcolumn)]"> 
>>>>
>>>>      <xsl:variable name="p" select="position()"/>
>>>>      <xsl:variable name="l" select="last()"/>
>>>>      <xsl:variable name="dbcolumn" select="@dbcolumn"/>
>>>>      <xsl:for-each select="$dbdef">
>>>>         <xsl:if test="key('dbdef-cols', $dbcolumn)">
>>>>            <xsl:value-of select="$dbcolumn"/>
>>>>            <xsl:if test="$p &lt; $l">
>>>>               <xsl:text>, </xsl:text>
>>>>            </xsl:if>
>>>>         </xsl:if>
>>>>      </xsl:for-each>
>>>>   </xsl:for-each>
>>>>
>>>> The output of this fragment might be:
>>>>
>>>> select col1, col2, col3
>>>>
>>>> This all works fine, except for one case - where the last column is
>>>> not found in the $dbdef file (where the 'if test=key' fails). Then I
>>>> get:
>>>>
>>>> select col1, col2,
>>>>
>>>> The position() < last() test doesn't work here. Can someone see a
>>>> better way to avoid that last comma?
>>>>
>>>> Thanks,
>>>> John Sands
>>>
> 


-- 

System Development
VIRBUS AG
Fon  +49(0)341-979-7419
Fax  +49(0)341-979-7409
joerg.heinicke@virbus.de
www.virbus.de


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]