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 November 21st, 2006, 08:49 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default KEY - GROUPING

Hi,

NOTE: I use XSLT 1.0 and MSXML

I am reading Jeni's tutorial on grouping using the Muenchian Method to see if I can understand it but have a few questions about it.

This is the example XML

<?xml version="1.0" encoding="UTF-8"?>
<records>
  <contact id="0001">
    <title>Mr</title>
    <forename>John</forename>
    <surname>Smith</surname>
  </contact>
  <contact id="0002">
    <title>Dr</title>
    <forename>Amy</forename>
    <surname>Jones</surname>
  </contact>
  <contact id="0003">
    <title>Mr</title>
    <forename>Colin</forename>
    <surname>Pallone</surname>
  </contact>
  <contact id="0004">
    <title>Miss</title>
    <forename>Jessica</forename>
    <surname>Pallone</surname>
  </contact>
</records>

I started with this simple XSLT to see what is going on:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="contacts-by-surname" match="contact" use="surname" />
<xsl:template match="records">
<xsl:for-each select="key('contacts-by-surname', 'Pallone')">
  <xsl:value-of select="key('contacts-by-surname', 'Pallone')" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

For my surprise, this code is repeating the same node. This is the output I get even though I am using a for loop to loop through the key that has a surname node with Pallone as value.

MrColinPalloneMrColinPallone

I thought the output would be:

MrColinPalloneMissJessicaPallone

since I have two <surname> nodes with different <forename> nodes.

1 - I would like to understand why this is happening.


Further in the tutorial, this construction is used:

<xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]">

2 - I do not understand why we have to use the count() function here.

3 - Also count(.) - means count the context node right ?

4 - What does the '|' mean in this expression?

5 - After the '|' we have this expression but the tutorial does not explain in detail what it means.
       key('contacts-by-surname', surname)[1]) = 1]


I would be very grateful if you could help to understand it.

Cheers,

CPall
 
Old November 22nd, 2006, 03:05 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

I would suggest picking up the following:

Beginning XSLT 2.0 From Novice to Professional - Jeni Tennison

Beginning XSLT - Jeni Tennison

XSLT 2.0 Programmer's Reference, 3rd Edition by Michael Kay

Learning XSLT By Michael Fitzgerald


 
Old November 22nd, 2006, 07:26 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi bonekrusher,

I am still using XSLT 1.0. and have already read Michael Kay's XSLT 1.0 book. But we don't learn everything at once. The reason why I am trying to understand this is because I am having speed problems with one of my transformations and think this can help.

Also, I managed to find some info online and have a better understanding now.

We use '|' to compare the context node to the one in the key. Right ?

One thing howevers I am still not sure about is why we use this - [1])=1

I think the [1] is like an array so we select the first nonde(but what first node the context or the key ?)

Also why we need to use count()=1 ?

Please could you elaborate a bit on that.

Cheers

CPall





)[1]) = 1
 
Old November 22nd, 2006, 09:35 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

No worries, CPall, I am learning also. I was suggesting those books because they could help you a lot. I can try to help:

'|' - This and like saying "AND". This an an XPath Operator. It computes two node-sets

For the other questions, can you post the whole code? Just seeing <xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]"> doesnt help me much. I'll try to help, if you post the whole template.

Regards
Bones



 
Old November 23rd, 2006, 04:45 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

You are asking for all the contacts that have a surname Pallone. You are then outputting the xsl:value-of all the contacts that have have the surname Pallone. This consists of two nodes therefore value-of outputs the text value of the first node.
Change:
Code:
<xsl:value-of select="key('contacts-by-surname', 'Pallone')" />
to
Code:
<xsl:value-of select="." />
--

Joe (Microsoft MVP - XML)
 
Old November 23rd, 2006, 11:13 AM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Bones, Joe,

Thanks for your reply.

Joe, thanks for the correction. However, could you plese clarify to me the points I made in my previous email. I would like to understand how it works in detail.

Here is the code Bones:

<xsl:key name="contacts-by-surname" match="contact" use="surname" />

<xsl:template match="records">
<xsl:for-each select="key('contacts-by-surname', 'Pallone')">

<xsl:value-of select="." />
</xsl:for-each>
</xsl:template>
 
Old November 23rd, 2006, 11:27 AM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Sorry Bones,

This is the code I am using inside the template:

<xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]">
 - <xsl:value-of select="surname" />,<br />
</xsl:for-each>
 
Old November 23rd, 2006, 01:34 PM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Have you read through the article on grouping at Jeni Tennison's site? The link is in the first post in this forum. The | operator is used to union nodes. If you union two nodes that are actually the same then you get a set with only one node, by comparing the count to one you then know that the first node returned from the key is the context node. That way you get a distinct list of surnames.

--

Joe (Microsoft MVP - XML)
 
Old November 23rd, 2006, 08:14 PM
Friend of Wrox
 
Join Date: Oct 2003
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Thanks Joe,

Yeap, I read Jeni's article first thing but was still not sure about some of the syntax
 
Old December 11th, 2006, 06:19 AM
Authorized User
 
Join Date: Sep 2006
Posts: 92
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi guys,

This is exactly the same issue that I have and I have found that switching from generate-id() to ...

 <xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]">

... (as Pallone has quoted) can (in some circumstances) really reduce response times.

However, my problem is that I need to also incorporate a filter and am having trouble getting the filter to return the right values. Maybe you guys can check out my thread (speed and grouping) and see if it helps you and if you have any ideas on filter syntax.

Many thanks,
Alan Searle






Similar Threads
Thread Thread Starter Forum Replies Last Post
test if current-grouping-key() has changed? bonekrusher XSLT 4 October 24th, 2008 10:35 AM
Value of parent element of current-grouping-key() bonekrusher XSLT 2 September 9th, 2007 06:29 AM
Protect cells and allow grouping/un-grouping sfreuden Excel VBA 4 December 14th, 2006 08:01 AM
<bean:message key="PNR.INPUT"/> key has null value warsha_14 Struts 1 November 13th, 2006 07:26 AM
TAB KEY working together KEY PRESS event thomaz C# 4 August 20th, 2006 02:47 PM





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