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

September 13th, 2009, 06:18 PM
|
|
Authorized User
|
|
Join Date: Nov 2007
Posts: 33
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
how to increment global variable
Hi,
I'm using XSLT 2.0
I would like to have a value that increment every now and then.
For example:
Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="position" select="0"/>
<xsl:template match="/">
<xsl:if test="my test goes here">
<!-- INCREMENT position -->
</xsl:if>
</xsl:template>
</xsl:stylesheet>
output
Code:
<library>
<book number="1">
<title>ABC</title>
</book>
<book number="2">
<title>DEF</title>
</book>
</library>
Is there a way in XSLT2.0 so I can increment like for example $position+1
Thanks,
|
|

September 14th, 2009, 07:10 AM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
Show us the XML input you have and the corresponding output you want to create and we can show you an XSLT way to achieve that.
If you want to number elements then you can often achieve that using the xsl:number instruction or sometimes it might suffice to simply call the position() function.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

September 14th, 2009, 03:51 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
The phrase "now and then" suggests that you are thinking of stylesheet execution as a temporal sequence of events. That's not the way functional programming works. You need to get out of your procedural mindset and think declaratively.
Is the number "1", "2", etc a function of something in the input? If so, express it functionally. If not, you may need a two-phase process: first generate the output without the numbers, then in the second phase use xsl:number to add the numbers.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

September 20th, 2009, 06:56 PM
|
|
Authorized User
|
|
Join Date: Nov 2007
Posts: 33
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Hi,
Thanks for the reply.
the number "1","2", etc is not from the input.
I want to generate the number as a sequence execution.
Sorry for not being details.
What I'm actually want to do is have a counter to count how many element that I created in the output. Something like position(), but instead counting the input position, I would like to count the output position. The problem is the element name could be different.
example output. and unfortunately the output structure is not under my controll. So I have to create in this structure.
<library>
<book number="1">
<title>ABC</title>
</book>
<book number="2">
<title>DEF</title>
</book>
<magazine number="3">
<title>DEF</title>
</magazine>
<newspaper number="4">
<title>GSHDAG</title>
</newspaper>
</library>
Is the 2 process the only way to do this?
Thanks,
|
|

September 21st, 2009, 04:04 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
>Is the 2 process the only way to do this?
From the information provided, yes. If you were prepared to give more information about the problem we might be able to come up with a better way, but it seems you aren't.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

September 21st, 2009, 03:52 PM
|
|
Authorized User
|
|
Join Date: Nov 2007
Posts: 33
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Hi,
Sorry for being so unclear, here I try again
I'm using Java to transform my xslt.
my input xml
Code:
<materials>
<material id="A">
<type>magazine</type>
<title>ABC</title>
</material>
<material id="B">
<type>newspaper</type>
<title>DEF</title>
</material>
<material id="">
<type>article</type>
<title>GHI</title>
</material>
</material>
I would like the output to be like this. with "number" is incrementing everytime i'm creating a new element (doesn't matter with the element name, it'll will continuesly increment number)
Code:
<library>
<book number="1">
<title>ABC</title>
</book>
<book number="2">
<title>DEF</title>
</book>
<article data="this is article" number="3"/>
<magazine number="4">
<title>GHI</title>
</magazine>
</library>
xslt:
Code:
<xsl:template match="material">
<xsl:if test="id=''">
<!-- here create element article -->
<!-- then create magaazine -->
</xsl:if>
</xsl:template>
I hope this will give you more information 
Last edited by geek.shrek; September 21st, 2009 at 06:26 PM..
Reason: add info
|
|

September 22nd, 2009, 04:50 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
So, the number is indeed a function of your input. Something like this:
Code:
<xsl:template match="material[type='magazine']">
<book number="{1 + count(preceding-sibling::material) + count(preceding-sibling::material[type='article']}">
</book>
</xsl:template>
<xsl:template match="material[type='newspaper']">
<book number="{1 + count(preceding-sibling::material) + count(preceding-sibling::material[type='article']}">
</book>
</xsl:template>
<xsl:template match="material[type='article']">
<xsl:variable name="n" select="1 + count(preceding-sibling::material) + count(preceding-sibling::material[type='article']"/>
<article number="{$n}">
</article>
<magazine number="{$n+1}">
</magazine>
</xsl:template>
Now, this may not be particularly efficient. More efficient alternatives include
(a) a two pass solution, as mentioned previously
(b) a recursive solution, that processes the <material> elements using head-tail recursion, passing the current article number as a parameter on each call.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

September 23rd, 2009, 12:06 AM
|
|
Authorized User
|
|
Join Date: Nov 2007
Posts: 33
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Thanks Mr Kay,
I'm trying to use two-pass processing. But I am confused how can I copy the temporary tree and insert an attribute.
phase1.xslt
Code:
<xsl:template match="/" mode="phase1">
<xsl:element name="library">
<xsl:call-template name="templateA"/>
</xsl:element>
</xsl:template>
<xsl:template name="templateA" match="/" mode="phaseA">
<xsl:element name=book>
<xsl:apply-template/>
</xsl:element>
</xsl:template>
temporary tree output
Code:
<library>
<book>
<title>ABC</title>
</book>
<book>
<title>DEF</title>
</book>
<article data="this is article"/>
<magazine>
<title>GHI</title>
</magazine>
</library>
phase2.xslt
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:import href="phase1.xslt"/>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="data">
<xsl:apply-templates select="/" mode="phase1"/>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="$data" mode="phase2"/>
</xsl:template>
<xsl:template match="/" mode="phase2">
<!-- I'm stuck here -->
<xsl:copy-of select="//Library/*">
<xsl:value-of select="child::*"></xsl:value-of>
<xsl:attribute name="number">
<xsl:value-of select="position()"/>
</xsl:attribute>
</xsl:copy-of>
</xsl:template>
I was thinking to copy the temporary tree which I store in $data
and insert an attribute "number". Will it possible to do this? 
|
|

September 23rd, 2009, 03:50 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
The second pass is a modified identity transform:
Code:
<xsl:template match="book|article|magazine" mode="pass2">
<xsl:copy>
<xsl:attribute name="number">
<xsl:number count="book|article|magazine"/>
</xsl:attribute>
<xsl:copy-of select="@* | node()"/>
</xsl:copy>
</xsl:template>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|
 |