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

August 25th, 2008, 03:04 PM
|
Registered User
|
|
Join Date: Aug 2008
Posts: 8
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Extracting a number range from tag attribute group
Hi folks,
I'm new to XSLT, have spent a couple of weeks with Michael Kay's book, and now I'm stuck with a task that seems to require a bit more experience. Consider the following XML source:
<group>
<foo bar="one"/>
<foo bar="two"/>
<foo bar="one"/>
<foo bar="one"/>
<foo bar="one"/>
<foo bar="three"/>
<foo bar="one"/>
<foo bar="one"/>
</group>
I now need a template or function that, fitted with "one" as argument, delivers the following number sequence: 1 1 3 5 7 8. In other words, I need pairs of numbers that identify the index of each "one" group. I don't need the nodes, I need their indexes within <group>.
I tried a <xsl:for-each-group> but couldn't manage to get the index of the nodes within the original <group>. I tried serveral different recursive functions. I tried various XPath expressions including for..to..return loops, selections and predicates. All the code tended to grow beyond anything reasonable and still not deliver the required results.
Any help is greatly appreciated. I'm using Saxon B9.
Maik
|

August 25th, 2008, 04:22 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Sorry if I'm being thick, but I can't see the relationship between your input and the sequence 1 1 3 5 7 8. Could you explain more clearly?
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|

August 25th, 2008, 04:25 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Ah, I've got it now. You find a group of consecutive "one" elements and then output the positions of the first and last items of the group.
Looks like
<xsl:for-each-group select="foo" group-adjacent="@bar">
<xsl:if test="current-grouping-key()=$arg">
<xsl:number select="current-group()[1]"/>
<xsl:number select="current-group()[last()]"/>
</xsl:if>
</xsl:for-each-group>
(plus some whitespace where needed)
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|

August 25th, 2008, 04:28 PM
|
Registered User
|
|
Join Date: Aug 2008
Posts: 8
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Thanks for the reponse, Michael.
Of all <foo> tags within <group>, I'm selecting those that have bar="one", and of those their indexes within the group. These are: 1, 3, 4, 5, 7, 8. Now I need these expressed in pairs of ranges of adjacent "one" tags. These groups are: 1-1, 3-5, 7-8.
Sorry for obfuscating that ;)
Maik
|

August 25th, 2008, 04:39 PM
|
Registered User
|
|
Join Date: Aug 2008
Posts: 8
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Thanks for the example!
Now I forgot to mention that there can also be <foo> tags without the bar attribute, which leads to the following problem with your code:
An empty sequence is not allowed as the @group-adjacent attribute of xsl:for-each-group
Maik
|

August 25th, 2008, 04:45 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Then do
group-adjacent="(@bar, '~~~~')[1]"
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference
|

August 25th, 2008, 04:54 PM
|
Registered User
|
|
Join Date: Aug 2008
Posts: 8
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
That works fine. And I twiddled with that for two days... but I never would have gotten to the '~~~~' part so fast. I have to read that up in your book!
EDIT: ok, that's just a random string to ensure that there's never an empty sequence, got it.
Thanks a lot, great support! :)
Maik
|
|
 |