xsl-list
[Top] [All Lists]

Re: grouping/position problem

2005-04-22 07:12:30
by all mean 

should be

by all means :D

On 4/22/05, M. David Peterson <m(_dot_)david(_dot_)x2x2x(_at_)gmail(_dot_)com> 
wrote:
Bruce (and group),

I am still trying to find a stopping point but before it got too late
I thought it best to showcase a quick sample of how you would go about
solving this problem using the sample XML you provided.  I will
convert this into the proper namespaces and elements and check it in
as soon as I can finish up this other item.

The XML I used was:

<?xml version="1.0" encoding="UTF-8"?>
<list>
  <item author="five" year="2001"/>
  <item author="three" year="2003"/>
  <item author="four" year="2002"/>
  <item author="two" year="1998"/>
  <item author="one" year="2005"/>
  <item author="two" year="2000"/>
  <item author="four" year="1999"/>
</list>

Which I then processed with the following XSLT 2.0-based stylesheet:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <author>
            <xsl:apply-templates select="list"/>
        </author>
    </xsl:template>
    <xsl:template match="list">
        <xsl:for-each-group select="item" group-by="@author">
            <author-group author="{(_at_)author}">
                <xsl:apply-templates select="current-group()">
                    <xsl:sort select="@author"/>
                    <xsl:sort select="@year"/>
                </xsl:apply-templates>
            </author-group>
        </xsl:for-each-group>
    </xsl:template>
    <xsl:template match="item">
        <item>
            <xsl:choose>
                <xsl:when test="position() = 1">
                    <xsl:apply-templates select="@author"/>
                    <xsl:apply-templates select="@year"
mode="standard-year-output"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="@year"
mode="shorten-year-output"/>
                </xsl:otherwise>
            </xsl:choose>
        </item>
    </xsl:template>
    <xsl:template match="@author">
        <xsl:attribute name="year">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
    <xsl:template match="@year" mode="standard-year-output">
        <xsl:attribute name="year">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
    <xsl:template match="@year" mode="shorten-year-output">
        <xsl:attribute name="year">
            <xsl:value-of select="substring(., 3)"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

When processed the following is the result output:

<?xml version="1.0" encoding="UTF-8"?>
<author>
    <author-group author="five">
        <item year="2001"/>
    </author-group>
    <author-group author="three">
        <item year="2003"/>
    </author-group>
    <author-group author="four">
        <item year="1999"/>
        <item year="02"/>
    </author-group>
    <author-group author="two">
        <item year="1998"/>
        <item year="00"/>
    </author-group>
    <author-group author="one">
        <item year="2005"/>
    </author-group>
</author>

A couple things to note:

- The output could have just as easily have been text.  But to
showcase where each author group starts and stops as well as the years
contained within each group I felt this would be easier to understand
for someone looking at this without any backround.
- If XML was the format I would need this to be in at this stage of
the transformation I would have probably held of from stripping the
date to its 2 digit shorthand... of course now that I said that I
realized I should have processed the date output using one of the many
great additions to the 2.0 spec, date processing :)  This will still
work fine of course and if I had more time I would change it right now
but for now I think its safe to leave it as is
:)
- actually there was one other point but for the life of me I cant
remember what it was.  If it comes to me and it seems important enough
to post I will do just that.

As I mentioned earlier I am finishing a few things on some other
projects but as soon as I am done with the new and improved version of
the projects stylesheet for this item I will check it in and ping you
to let you know.  If you need this before late afternoon you may want
to try to use the above as a guide to recreate the logic for that
stylesheet and if you get into a jam, ping me and I will see if I can
rearrange things a bit.

If any of the rest of you have comments, questions or concerns please,
by all mean :D

On 4/22/05, Bruce D'Arcus <bdarcus(_at_)gmail(_dot_)com> wrote:
I'm having some problems with grouping and position().

For illustration, you could imagine an input source like:

<list>
  <item author="five" year="2001"/>
  <item author="three" year="2003"/>
  <item author="four" year="2002"/>
  <item author="two" year="1998"/>
  <item author="one" year="2005"/>
  <item author="two" year="2000"/>
  <item author="four" year="1999"/>
</list>

I need to group and sort by author, then by year, and then pass some
parameters that are based on the item's position within -- in this case
-- the author group.

I have this template:

  <xsl:template match="mods:modsCollection" mode="sort_author-year">
    <xsl:variable name="bibref" select="mods:mods" />
    <xsl:for-each-group select="$bibref" group-by="bib:grouping-key(.)">
      <xsl:sort select="current-grouping-key()"/>
      <xsl:variable name="author-position" select="position()"/>
      <xsl:variable name="shorten-author" as="xs:boolean"
select="$author-position > 1" />
      <xsl:for-each-group select="current-group()"
group-by="bib:year(.)">
        <xsl:sort select="current-grouping-key()" />
       <xsl:variable name="year">
          <xsl:value-of select="current-grouping-key()"/>
         <xsl:if test="last() > 1">
           <xsl:number value="position()" format="a"/>
         </xsl:if>
       </xsl:variable>
        <xsl:for-each select="current-group()">
          <xsl:apply-templates select="mods:titleInfo">
            <xsl:with-param name="year" select="$year"/>
            <xsl:with-param name="shorten-author"
select="$shorten-author"/>
          </xsl:apply-templates>
        </xsl:for-each>
      </xsl:for-each-group>
    </xsl:for-each-group>
  </xsl:template>

The bib:grouping-key function constructs an author names string to sort.

The problem is the author-position variable.

What I want is for it to measure position within an author group.  But
I'm getting these sorts of results:

    AUTHOR POSITION: 1
    SHORTEN: false
    AUTHOR POSITION: 2
    SHORTEN: true
    AUTHOR POSITION: 2
    SHORTEN: true
    AUTHOR POSITION: 3
    SHORTEN: true
    AUTHOR POSITION: 4
    SHORTEN: true
    AUTHOR POSITION: 4
    SHORTEN: true
    AUTHOR POSITION: 5
    SHORTEN: true
    AUTHOR POSITION: 6

... which tells me it's measuring the position of the group itself.

What I'm wanting is:

    AUTHOR POSITION: 1
    SHORTEN: false
    AUTHOR POSITION: 1
    SHORTEN: false
    AUTHOR POSITION: 2
    SHORTEN: true
    AUTHOR POSITION: 1
    SHORTEN: false
    AUTHOR POSITION: 1
    SHORTEN: false
    AUTHOR POSITION: 2
    SHORTEN: true
    AUTHOR POSITION: 1
    SHORTEN: false
    AUTHOR POSITION: 1
    SHORTEN: false

How do I fix this?

Bruce

--~------------------------------------------------------------------
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>
--~--



--
<M:D/>

:: M. David Peterson ::
XML & XML Transformations, C#, .NET, and Functional Languages Specialist



-- 
<M:D/>

:: M. David Peterson ::
XML & XML Transformations, C#, .NET, and Functional Languages Specialist

--~------------------------------------------------------------------
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>