Re: [xsl] XSLT2, collection(), and xsl:key

Subject: Re: [xsl] XSLT2, collection(), and xsl:key
From: "James Cummings" <cummings.james@xxxxxxxxx>
Date: Fri, 1 Feb 2008 18:06:43 +0000
Hi again,

I must be missing something (I usually am), if I'm reading this (and
Andrew's grouping in a variable version), they both apply to all
elements, and here all elements with only a @type.  Part of my problem
is that I definitely *don't* want to do all elements, and in some
cases more than one attribute on some elements.  So I really need to
feed it a list of element/@attrib rather than just do everything
matching a pattern.

I mean I could build a list in the xslt in a variable something like:
<xsl:variable name="tables">
<table element="seg" att="type"/>
<table element="seg" att="sub-type"/>
<table element="other" att="type"/>
<table element="thing" att="name"/>
<!-- etc -->
</xsl:variable>

And then try the grouping selecting each $tables/table ?  Would that work?

-James

On Feb 1, 2008 5:45 PM, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> Looks to me something like this:
>
> <xsl:variable name="pop" select="collection('...')//*[@type]"/>
>
> <xsl:for-each-group select="$pop" group-by="node-name(.)">
>   <h1><xsl:value-of select="current-grouping-key()"/></h1>
>   <table>
>     <tr>
>       <td>document</td>
>       <xsl:variable name="types"
> select="distinct-values(current-group()/@type)"/>
>       <xsl:for-each select="$types">
>         <td><xsl:value-of select="."/></td>
>       </xsl:for-each>
>     </tr>
>     <xsl:for-each-group select="current-group()"
> group-by="ancestor::p/@xml:id">
>     <tr>
>       <td><xsl:value-of select="current-grouping-key()"/></td>
>       <xsl:for-each select="$types">
>         <td><xsl:value-of
> select="count(current-group()[@type=current()])"/></td>
>       </xsl:for-each>
>     </tr>
>   </table>
> </xsl:for-each-group>
>
> Michael Kay
> http://www.saxonica.com/
>
>
> > -----Original Message-----
> > From: James Cummings [mailto:cummings.james@xxxxxxxxx]
> > Sent: 01 February 2008 17:23
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: [xsl] XSLT2, collection(), and xsl:key
> >
> > Hiya,
> >
> > I'm using the collection() function and Saxon to produce some
> > statistics about how many of which elements of which type in
> > a particular set of documents.
> >
> > Let's say that document one has something like:
> >
> > <p xml:id="doc1" type="hypothetical">
> > There is some text with <seg type="foo">some foo</seg> and
> > occasionally <seg type="blort">blort</seg> and <other
> > type="wibble">wibble</other></p>
> >
> >
> > and document two (and up to some really large number) is like:
> >
> > <p xml:id="doc2">
> > There is another doc with <seg type="foo">some foo</seg> and
> > occasionally <seg type="notBlort">notBlort</seg> and <other
> > type="fluffy">fluffy other</other> and <some
> >   name="thing">someThing</some></p>
> >
> > What I want to produce are tables of counts of specific
> > elements, by document and type. So something like the
> > following (though using table/row/cell xml markup):
> >
> >
> > table: other
> > document | fluffy | wibble | stuff
> > doc1 | 0 | 1 | 0
> > doc2 | 1 | 0 | 0
> > doc3 | 20 | 12 | 54
> >
> > table: seg
> > document | blort | foo | notBlort
> > doc1 | 1 | 1 | 0
> > doc2 | 0 | 1| 1
> > doc3 | 23 | 44 | 58
> >
> > table: some
> > document | thing | else | now
> > doc1 | 0 | 0 | 0
> > doc2 | 1 | 0 | 0
> > doc3 | 12 | 5 | 24
> >
> > I can build this manually (and for one element I have done
> > so) by doing:
> >
> > <xsl:variable name="docs"
> > select="collection('../../working/xml/docs.xml')"/>
> > <xsl:template name="main">
> > <table><head>seg by type</head>
> > <row rend="label">
> > <cell>document</cell>
> > <cell>blort</cell>
> > <cell>foo</cell>
> > <cell>notBlort</cell>
> > </row>
> > <xsl:for-each select="$docs//p"> <!-- let's pretend p is the
> > root element --> <row> <xsl:variable name="doc"
> > select="@xml:id"/> <cell><xsl:value-of select="$doc"/></cell>
> > <cell><xsl:value-of select="count(.//seg[@type='blort'])</cell>
> > <cell><xsl:value-of select="count(.//seg[@type='foo'])</cell>
> > <cell><xsl:value-of select="count(.//seg[@type='notBlort'])</cell>
> > </row>
> > </xsl:for-each>
> > </table>
> > </xsl:template>
> >
> > But that isn't really the point now is it?  I tried to use
> > <xsl:key> but I ran into the problem of it not liking the
> > collection() function as part of the match.
> >
> > What I want to do is be able to say for-each doc, build me a
> > table of all the (let's pretend unknown) values of this
> > attribute on this element.  So something like:
> >
> > <xsl:for-each select="$docs//p">
> > <xsl:value-of select="my:function(other/@type, seg/@type,
> > thing/@name, new/@type)"/> </xsl:for-each>
> >
> > and without knowing the values of @type in advance it makes a
> > table like above of them (using distinct-values()?) and
> > counting their occurrences.
> >
> > This is a case where I know it must be possible, and I could
> > just go and do it manually, (in reality there are about 10
> > elements with a number of attributes, with around 20 values
> > each), but it just seems
> > *wrong* to do it that way. ;-)
> >
> > Suggestions?
> >
> > Thanks,
> >
> > -James

Current Thread