Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old July 13th, 2009, 10:29 AM
Friend of Wrox
 
Join Date: Jul 2006
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default Look up an ancestors attribute from a for-each-group

Hi, I am creating a back-of-the-book index which will result in an xsl-fo document. I am using grouping for my index. I am grouping on <indxref> and need get the closest @id from an ancestor. How can I do this with grouping?

Thanks

XML
Code:
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <chapter id="chapter1">
        <title id="title">
            <indxref indxlevel1="Stopping Procedures"/>
            <indxref indxlevel1="Procedures, Stopping"/>                 
        </title>
    </chapter>
   
</root>
XSLT
Code:
 <xsl:for-each-group select="//indxref" group-by="substring(@indxlevel1, 1,1)">
        <xsl:sort select="current-grouping-key()" order="ascending"/>
        <xsl:variable name="curID">
            <xsl:for-each select="ancestor::*[@id]">
                <xsl:if test="position() = last()">
                    <xsl:value-of select="@id"/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
    </xsl:for-each-group>
 
Old July 13th, 2009, 10:39 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Can you show us the result you want to get from the XML input you have posted?
Inside of the xsl:for-each-group the context node is the first item in each group so your code doing ancestor::*[@id] would look at the ancestor elements of the first item in each group. Note however that the closest ancestor in my understanding would be the first element on the ancestor axis as that is a reverse axis. So you could simply do
Code:
<xsl:variable name="curID" select="ancestor::*[@id][1]/@id"/>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
The Following User Says Thank You to Martin Honnen For This Useful Post:
bonekrusher (July 15th, 2009)
 
Old July 13th, 2009, 11:07 AM
Friend of Wrox
 
Join Date: Jul 2006
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default

Thanks for the help.

Code:
<xsl:variable name="curID" select="ancestor::*[@id][1]/@id"/>
This returns the first <indxref> ancestor::*[@id][1]/@id. Below is a working example.

Current output:

Code:
<out xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <result>title</result>
    <result>title</result>
</out>
Code:
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <chapter id="chapter1">
        <title id="title">
            <indxref indxlevel1="Stopping Procedures">
                <pcnarr>STOPPING PROCEDURE</pcnarr>
            </indxref>
            <indxref indxlevel1="Procedures, Stopping">
                <pcnarr/>
            </indxref>
        </title>
    </chapter>
    <chapter id="chapter2">
        <title id="title2">
            <indxref indxlevel1="Procedures">
                <pcnarr> PROCEDURE</pcnarr>
            </indxref>
            <indxref indxlevel1="Procedures, running">
                <pcnarr/>
            </indxref>
        </title>
    </chapter>
</root>
Code:
<?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" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <out>
            <xsl:for-each-group select="//indxref" group-by="substring(@indxlevel1, 1,1)">
                <xsl:sort select="current-grouping-key()" order="ascending"/>                
                <xsl:variable name="curID" select="ancestor::*[@id][1]/@id"/>
                <result>
                    <xsl:value-of select="$curID"/>
                </result>
            </xsl:for-each-group>
        </out>
    </xsl:template>
</xsl:stylesheet>
I am using saxon 9.1.0.5

My desired result would be:
Code:
<out xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <result>title</result>
    <result>title</result>
    <result>title2</result>
    <result>title2</result>
</out>
 
Old July 13th, 2009, 11:12 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

You need an inner for-each on the current group otherwise you are just looping once per group, not once for each item in the group:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
   <xsl:template match="/">
       <out>
           <xsl:for-each-group select="//indxref" group-by="substring(@indxlevel1, 1,1)">
               <xsl:sort select="current-grouping-key()" order="ascending"/>
               <xsl:for-each select="current-group()">
               <xsl:variable name="curID" select="ancestor::*[@id][1]/@id"/>
               <result>
                  <xsl:value-of select="$curID"/>
               </result>
               </xsl:for-each>
           </xsl:for-each-group>
       </out>
   </xsl:template>
</xsl:stylesheet>
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
The Following User Says Thank You to samjudson For This Useful Post:
bonekrusher (July 13th, 2009)
 
Old July 13th, 2009, 11:27 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

You might not need the xsl:for-each-group then:
Code:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <out>
            <xsl:for-each select="//indxref">
                <xsl:sort select="substring(@indxlevel1, 1,1)"/>
                <result>
                      <xsl:value-of select="ancestor::*[@id][1]/@id"/>
                </result>
            </xsl:for-each>
        </out>
    </xsl:template>
</xsl:stylesheet>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
The Following User Says Thank You to Martin Honnen For This Useful Post:
bonekrusher (July 13th, 2009)
 
Old July 13th, 2009, 12:08 PM
Friend of Wrox
 
Join Date: Jul 2006
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default

Thanks Martin and Sam.

Sam's solution will work as I am actually doing multi-grouping.

Thanks for all the help.

Phil





Similar Threads
Thread Thread Starter Forum Replies Last Post
searching children of ancestors mphare XSLT 2 October 8th, 2008 01:09 PM
Extracting a number range from tag attribute group maikm XSLT 6 August 25th, 2008 04:54 PM
Restart new group number in Group Footer sukarso Crystal Reports 2 October 13th, 2006 12:11 PM
Access to attribute values from class of attribute jacob C# 1 October 28th, 2005 01:11 PM
Group XML by Attribute values? NotesSensei XSLT 4 July 14th, 2004 11:53 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.