xsl-list
[Top] [All Lists]

RE: [xsl] variable as element name; issues with for-each-group

2007-07-11 09:35:23
How do I 
filter out extra elements when any predicates added to * seem 
to break it?

<xsl:for-each-group select="* except author">

or

<xsl:for-each-group select="*[not(self::author)]"> 

Is 
there a mechanism to ignore anything before the first "genus" 
when doing the grouping? 

<xsl:for-each-group select="* except genus[1]/preceding-sibling::*)"

I'm having trouble with current-group() and
position() in for-each-group. Basically, nothing works.

<family name="{current-group()[1]}"> 

gives me the whole sequence when it's clear it should only 
return the first element.

You did group-starting-with="family", so it seems likely that
current-group()[1] is a <family> element, which has a complex internal
structure. I suspect you don't want the string-value of the <family>
element, you want the value of its name attribute, that is  <family
name="{current-group()[1]/@name}"> 

I'd like to replace

subsequence(current-group(),2) 

with something like 

subsequence(current-group(),./superfamily[1]/position())

but again it doesn't seem to work (seems to come up with no matches).

Almost certainly a context problem. If you're within for-each-group then it
seems unlikely that the context node has a child called superfamily. And
using position() on the rhs of "/" almost certainly means something
different from what you would like it to mean.

Michael Kay
http://www.saxonica.com/


-----Original Message-----
From: Thomas Kielczewski [mailto:thomaskiel(_at_)yahoo(_dot_)com] 
Sent: 11 July 2007 16:53
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] variable as element name; issues with for-each-group

Hi,
Please bear with me as this is a triple-shot of newbie questions.

I have the following simplified XML:

<section name="Species Accounts">
<author>someone</author>
  <chapter>1</chapter>
    <superfamily>True Butterflies</superfamily>
      <description>
         <p>The true butterflies have antennae with rounded clubs</p>
      </description>
    <family>
      <name>Swallowtails</name>
        <description>
          <p>The swallowtails are worldwide in distribution.</p>
        </description>
    </family>
    <species>
        <name>Cattle Heart Swallowtail</name>
    </species>
    <genus>
        <name>Pipevine Swallowtails</name>
        <description>This is a primarily tropical genus.</description>
    </genus>
    <species>
        <name>Pipevine Swallowtail</name>
    </species>
    <species>
        <name>Polydamas Swallowtail</name>
    </species>
  <chapter>2</chapter>
...
</section>


I am giving it this structure:

<section>
  <chapter id="1">
    <superfamily name="...">
      <description/>
      <family name="...">
         <description/>
         <species>...</species>
          ...
         <genus>
           <species>...</species>
          ...
         </genus>
          ...
      </family>
    <superfamily>
  </chapter>
  <chapter>
  ...
  </chapter>
</section>


This is going well, but with a few sticky issues:

1) This is my outer for-each-group:

<xsl:for-each-group group-starting-with="chapter"
select="*">
  <chapter>
  ...
  </chapter>
</xsl:for-each-group>

The problem is that this seems to pick up orphan elements I'd 
rather leave alone, like "author" in the XML above, and 
recasting them as "chapter" (complete with "id"). How do I 
filter out extra elements when any predicates added to * seem 
to break it?

Same idea when I group "species" under "genus", because some 
species are not in a genus but directly under "family." Is 
there a mechanism to ignore anything before the first "genus" 
when doing the grouping? (This is where the higher-order 
species will always be located.) Or is this done with some 
crafty predicates?

2) I'm having trouble with current-group() and
position() in for-each-group. Basically, nothing works.

<family name="{current-group()[1]}"> 

gives me the whole sequence when it's clear it should only 
return the first element.

Then, rather than explicitly stating the cutoff point in

<xsl:for-each-group group-starting-with="superfamily"
select="subsequence(current-group(),2)">

I'd like to replace

subsequence(current-group(),2) 

with something like 

subsequence(current-group(),./superfamily[1]/position())

but again it doesn't seem to work (seems to come up with no matches).


This is the entire XSLT:

<xsl:stylesheet
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
 
   <xsl:output
        indent="yes"
        method="xml" />
    <xsl:strip-space
        elements="*" />

    <xsl:template
        match="section">
        <xsl:result-document
            href="a.xml">

            <section
                title="{(_at_)name}">

                <xsl:for-each-group
                    group-starting-with="chapter"
                    select="*">
                    <chapter
                        id="{current-group()[1]}">

                        <xsl:for-each-group
                           
group-starting-with="superfamily"
                           
select="subsequence(current-group(),2)">
                            <superfamily
                               
name="{current-group()[1]}">
  
                                <xsl:for-each-group
                                   
group-starting-with="family"
                                   
select="subsequence(current-group(),2)">
                                    <family
                                       
name="{current-group()[1]}">
                                          
<xsl:copy-of
                                           
select="following::description[1]" />
                                        
                                       
<xsl:for-each-group
                                           
group-starting-with="genus"
                                           
select="subsequence(current-group(),2)">
                                            <genus 
name="{current-group()[1]}">
                                                
                                               
<xsl:for-each-group
                                                   
group-starting-with="species"
                                                   
select="subsequence(current-group(),2)">
                                                    
                                                   
<species name="{current-group()[1]}">
                                                      
<xsl:copy-of select="."/>
                                                      

                                                  
</species>
                                               
</xsl:for-each-group>
                                            </genus>
                                        
</xsl:for-each-group>    
                                    </family>
                                </xsl:for-each-group>
                            </superfamily>
                        </xsl:for-each-group>
                    </chapter>
                </xsl:for-each-group>
            </section>
         </xsl:result-document>
     </xsl:template>
</xsl:stylesheet>


3) Eventually, I'd like to clean up the repeating elements of 
my template and make each level a template call using 
parameters. But I can't even make a call to a variable work. 
I declare my variable as a top-level element, shouldn't it be 
visible to all? What crucial ingredient am I missing? I tried 
this with braces and
without:

<xsl:stylesheet
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
...
<xsl:variable
        name="level2"
        select="'superfamily'" />

<xsl:template match="section">
...
<xsl:for-each-group
                           
group-starting-with="{$level2}"
                           
select="subsequence(current-group(),2)">
<xsl:element name="{$level2}">
<xsl:attribute name="name"
select="current-group()[1]"/>
...
</xsl:element>
</xsl:for-each-group>
</xsl:template>


This newbie has been XSLT'ing for a little over a month now. 
He's using Saxon 8B on <oXygen/> 8.2.  

Thanks, and congratulations for the great discussions that 
occasionally pop up on this forum.


Thomas Kielczewski
Modality, LLC
Durham, NC


       
______________________________________________________________
______________________Ready for the edge of your seat? 
Check out tonight's top picks on Yahoo! TV. 
http://tv.yahoo.com/

--~------------------------------------------------------------------
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(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
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(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>