Subject: RE: [xsl] variable as element name; issues with for-each-group From: "Michael Kay" <mike@xxxxxxxxxxxx> Date: Wed, 11 Jul 2007 17:34:53 +0100 |
>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@xxxxxxxxx] > Sent: 11 July 2007 16:53 > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx > 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="{@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/
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] variable as element name;, David Carlisle | Thread | [xsl] RE: xsl-list Digest 12 Jul 20, shi wudao |
Re: [xsl] variable as element name;, David Carlisle | Date | Re: [xsl] Tricky transformation tas, David Carlisle |
Month |