RE: [xsl] Using key and position()

Subject: RE: [xsl] Using key and position()
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Tue, 16 Nov 2004 18:56:47 -0000
position() returns the position of a node in the list of nodes that you are
currently iterating over. So

<xsl:variable name="parentGroup">
  <xsl:for-each select="ParentGroup">
    <parentgroup id="generate-id()" pos="position()"/>
  </xsl:for-each>
</xsl:variable>

will give you values 1,2,3 etc.

You will get what you are looking for by:

<xsl:variable name="parentGroup">
  <xsl:for-each select="*">
    <xsl:if test="self::parentGroup">
       <parentgroup id="generate-id()" pos="position()"/>
    </xsl:if>
  </xsl:for-each>
</xsl:variable>

However, there might be a much easier way of doing what you are trying to
do, if you explained your overall problem rather than your approach to
solving it.

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

> -----Original Message-----
> From: Bhupendra Singh [mailto:skbhupendra@xxxxxxxxxxx] 
> Sent: 16 November 2004 16:13
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Using key and position()
> 
> Hi,
> I have an input XML like this:
> 
> <action>
> 	- <ParentGroup> Node1 </ParentGroup>
> 	- <ChildGroup> Node1.1 </ChildGroup>
> 	- <Child Node1>1.1.1 </Child Node1>
> 	- <Child Node2>1.1.2 </Child Node2>
> 	- <ParentGroup> Node1 </ParentGroup>
> 	- <ChildGroup> Node1.2 </ChildGroup>
> 	- <Child Node1>1.2.1 </Child Node1>
> 	- <Child Node2>1.2.2 </Child Node2>
> 	- <ParentGroup> Node1 </ParentGroup>
> 	- <ChildGroup> Node1.3 </ChildGroup>
> 	- <Child Node1>1.3.1 </Child Node1>
> 	- <Child Node2>1.3.2 </Child Node2>
> 	- <ParentGroup> Node1 </ParentGroup>
> 	- <ChildGroup> Node1.3 </ChildGroup>
> 	- <Child Node1>1.3.x </Child Node1>
> 	- <Child Node2>1.3.y </Child Node2>
> 
> 	- <ParentGroup> Node2 </ParentGroup>
> 	- <ChildGroup> Node2.1 </ChildGroup>
> 	- <Child Node1>2.1.1 </Child Node1>
> 	- <Child Node2>2.1.2 </Child Node2>
> 	- <ParentGroup> Node2 </ParentGroup>
> 	- <ChildGroup> Node2.2 </ChildGroup>
> 	- <Child Node1>2.2.1 </Child Node1>
> 	- <Child Node2>2.2.2 </Child Node2>
> 	- <ParentGroup> Node2 </ParentGroup>
> 	- <ChildGroup> Node2.3 </ChildGroup>
> 	- <Child Node1>2.3.1 </Child Node1>
> 	- <Child Node2>2.3.2 </Child Node2>
> ...........
> </action>
> 
> I want to capture the position of each of the
> <ParentGroup> elements and store it in a variable by
> going through the document only once. 
> 
> <xsl:variable name="parentGroup">
>   <xsl:for-each select="ParentGroup">
>     <parentgroup id="generate-id()" pos="position()"/>
>   </xsl:for-each>
> </xsl:variable>
> 
> 
> Then I want to use this variable to get the position
> of each <ParentGroup> and find its coresponding
> <ChildGroup> and <Child Nodes>.
> 
> When I print the contents of the variable(@id and
> @pos), then I find that the content is correct, but
> when I try to retreive the content using key then I
> get nothing.  Here is the XSL that I have.
> 
> 
> <?xml version="1.0" ?>
> <xsl:stylesheet
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> version="1.0">
> 
> <!-- Key to group distinct ChildGroup's -->
> <xsl:key name="SEC_CUST" match="ChildGroup" use="."/>
> 
> <!-- Key to group distinct ParentGroup's -->
> <xsl:key name="PRI_CUST" match="ParentGroup" use="."/>
> 
> <!-- Key to find position of ParentGroup's -->
> <xsl:key name="parentGroups" match="parentGroup"
> use="@id"/>
> 
> <xsl:template match="/">
> 	<xsl:apply-templates/>
> </xsl:template>
> 
> 
> <xsl:template match="action">
> <TRANS_OUTPUT>
> <CUSTOMERS>
> <xsl:variable name="var_24" select="Child Node1" />
> <xsl:variable name="var_27" select="Child Node2" />
> 
> <!-- Variable to store the posittion of each
> ParentGroup nodes -->
> <xsl:variable name="parentGroup"> 
>   <xsl:for-each select="ParentGroup">
>     <parentgroup>
>     <xsl:attribute name="id" select="generate-id()"/>
>     <xsl:attribute name="pos" select="position()"/>
>     </parentgroup>
>   </xsl:for-each>
> </xsl:variable>
> 
>   <xsl:for-each select="$var_21[count(. |
> key('PRI_CUST', .)[1]) = 1]">
>   <PRIMARY CUSTOMER>
>      <xsl:variable name="priId" select="." />
>      <xsl:variable name="p"
> select="key('parentGroups', generate-id())/@pos" />
>      <PRI_HEADER><xsl:value-of select="$p"/>
>           <xsl:value-of select="$var_27[$p]"/>
>      </PBU_HEADER>
>      <PRIMARY_CUST_DESC>
>         <xsl:value-of select="$var_24[$p]"/>
>         <xsl:text> </xsl:text>
>         <xsl:value-of select="$priId"/>
>      </PRIMARY_CUST_DESC>
> 
>      <SECONDARY CUSTOMER> 
>       <xsl:for-each select= SECONDARY CUSTOMER....
>       ....group &.Do processing for Sec customers
>      </SECONDARY CUSTOMER> 
> 
>     </End of for loop for Primary cusotmer>
>     </PRIMARY CUSTOMER>
> </CUSTOMERS>
> </TRANS_OUTPUT>
> 
> 
> In the above XSL..I get the value of $p undefined 
> 
> <xsl:variable name="p" select="key('parentGroups',
> generate-id())/@pos" />
> 
> So when I access $var_27[$p] and $var_24[$p] ..I get
> nothing.
> 
>      <PRI_HEADER><xsl:value-of select="$p"/>
>           <xsl:value-of select="$var_27[$p]"/>
>      </PBU_HEADER>
>      <PRIMARY_CUST_DESC>
>         <xsl:value-of select="$var_24[$p]"/>
>         <xsl:text> </xsl:text>
>         <xsl:value-of select="$priId"/>
>      </PRIMARY_CUST_DESC>
> 
> 
> Can someone please let me know what has gone wrong.
> 
> 
> 
> 
> 		
> ___________________________________________________________ 
> Win a castle for NYE with your mates and Yahoo! Messenger 
> http://uk.messenger.yahoo.com

Current Thread