Group and Sequence combination in xslt 2.0

R

RolfK

Dear ALL,
I need some help on xsl:sequence. I'm using the Altova XSLT processor,
but I'm quite confident it is not an processor issue. It's probably my
bad knowledge of xslt 2.0.
I have probably put more that required in the test case, but it
basically covers my more complex code.

Here is the xml example source:
<?xml version="1.0" encoding="UTF-8"?>
<SeqTest>
<Item>otto_L</Item>
<Item>otto_L</Item>
<Item>otto_R</Item>
<Item>otto_L</Item>
<Item>karl_L</Item>
<Item>karl_R</Item>
<Item>nepumuk_L</Item>
</SeqTest>
My xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsl:eek:utput method="xml" version="1.0" encoding="UTF-8" indent="yes"/ <xsl:template match="/">
<DEBUG>
<xsl:for-each select="SeqTest/Item">
<ForeEach Pos="{position()}" Name="{.}"/>
</xsl:for-each>
<xsl:variable name="vSeq">
<xsl:for-each-group select="SeqTest/Item"
group-by="substring(.,1,string-length(.)-2)">
<xsl:variable name="vBaseName" s
elect="substring(.,1,string-length(.)-2)"/>
<xsl:if test="$vBaseName != 'nepumuk'">
<xsl:sequence select="$vBaseName"/>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<Seq>
<xsl:for-each select="$vSeq">
<Item BaseName="{.}"/>
</xsl:for-each>
</Seq>
</DEBUG>
</xsl:template>
</xsl:stylesheet>
The UNEXPECTED result
<?xml version="1.0" encoding="UTF-8"?>
<DEBUG xmlns:xs="http://www.w3.org/2001/XMLSchema">
<ForeEach Pos="1" Name="otto_L"/>
<ForeEach Pos="2" Name="otto_L"/>
<ForeEach Pos="3" Name="otto_R"/>
<ForeEach Pos="4" Name="otto_L"/>
<ForeEach Pos="5" Name="karl_L"/>
<ForeEach Pos="6" Name="karl_R"/>
<ForeEach Pos="7" Name="nepumuk_L"/>
<Seq>
<Item BaseName="ottokarl"/>
</Seq>
</DEBUG>

As you can see the result element Item is only once there.
For me it meas that I have not build a sequnce of simple string values
over which I want to iterate.
(Please see attribute BaseName="otokarl" which indictes that too )

WHAT IS WRONG HERE ?

Any help is welcome

Rolf
 
M

Martin Honnen

RolfK said:
<xsl:variable name="vSeq">
<xsl:for-each-group select="SeqTest/Item"
group-by="substring(.,1,string-length(.)-2)">
<xsl:variable name="vBaseName" s
elect="substring(.,1,string-length(.)-2)"/>
<xsl:if test="$vBaseName != 'nepumuk'">
<xsl:sequence select="$vBaseName"/>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<Seq>
<xsl:for-each select="$vSeq">
<Item BaseName="{.}"/>
</xsl:for-each>
</Seq>

<Seq>
<Item BaseName="ottokarl"/>
</Seq>
</DEBUG>

As you can see the result element Item is only once there.
For me it meas that I have not build a sequnce of simple string values
over which I want to iterate.

The variable is currently a temporary tree. If you want a sequence of
strings then you need to use the 'as' attribute as follows:


<xsl:variable name="vSeq" as="xs:string*">
<xsl:for-each-group select="SeqTest/Item"
group-by="substring(.,1,string-length(.)-2)">
<xsl:variable name="vBaseName"
select="substring(.,1,string-length(.)-2)"/>
<xsl:if test="$vBaseName != 'nepumuk'">
<xsl:sequence select="$vBaseName"/>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>


Not related to your problem is the following suggestion: instead of
computing the "base name" again and again you can simply call the
current-grouping-key() function e.g.

<xsl:for-each-group select="SeqTest/Item"
group-by="substring(.,1,string-length(.)-2)">
<xsl:variable name="vBaseName" select="current-grouping-key()"/>
<xsl:if test="$vBaseName != 'nepumuk'">
<xsl:sequence select="$vBaseName"/>
</xsl:if>
</xsl:for-each-group>

or you could get rid of the variable completely:

<xsl:for-each-group select="SeqTest/Item"
group-by="substring(.,1,string-length(.)-2)">
<xsl:if test="current-grouping-key() != 'nepumuk'">
<xsl:sequence select="current-grouping-key()"/>
</xsl:if>
</xsl:for-each-group>
 
R

RolfK

The variable is currently a temporary tree. If you want a sequence of
strings then you need to use the 'as' attribute as follows:

                        <xsl:variable name="vSeq" as="xs:string*">
                                <xsl:for-each-group select="SeqTest/Item"
                                        group-by="substring(.,1,string-length(.)-2)">
                                        <xsl:variable name="vBaseName"
select="substring(.,1,string-length(.)-2)"/>
                                        <xsl:if test="$vBaseName != 'nepumuk'">
                                                <xsl:sequence select="$vBaseName"/>
                                        </xsl:if>
                                </xsl:for-each-group>
                        </xsl:variable>

Not related to your problem is the following suggestion: instead of
computing the "base name" again and again you can simply call the
current-grouping-key() function e.g.

<xsl:for-each-group select="SeqTest/Item"
                                        group-by="substring(.,1,string-length(.)-2)">
                                        <xsl:variable name="vBaseName" select="current-grouping-key()"/>
                                        <xsl:if test="$vBaseName != 'nepumuk'">
                                                <xsl:sequence select="$vBaseName"/>
                                        </xsl:if>
                                </xsl:for-each-group>

or you could get rid of the variable completely:

<xsl:for-each-group select="SeqTest/Item"
                                        group-by="substring(.,1,string-length(.)-2)">
                                        <xsl:if test="current-grouping-key() != 'nepumuk'">
                                                <xsl:sequence select="current-grouping-key()"/>
                                        </xsl:if>
                                </xsl:for-each-group>
--

        Martin Honnen
       http://JavaScript.FAQTs.com/- Zitierten Text ausblenden -

- Zitierten Text anzeigen -

Dear Martin,

Thanks a lot for this substancial and quick help !
I guess it will improve my code and even the key might inprove the
overall performance.

Rolf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top