473,324 Members | 2,196 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

XSLT - maintaining iteration count

I have an XSLT script that has to operate on some particularly nasty XML to
turn it into a SQL databse, but 'entries' in the XML aren't actually
unique, so their unique identifier is useless. I need to somehow create
crosslinked tables using the XSLT, but can only do this by maintaining a
counter for each line I write.

Is there a way to create a proxy 'increment' function that lets me maintain
a counter variable?

- Mike Kamermans
Jul 20 '05 #1
6 10584
To be more specific, I have an XML document consisting of entries roughly
like this:

<entry>
<seq_num>81732</seq_num>
<k_entries>
<k val="kval1"/>
<k val="kval2"/>
</k_entries>
<r_entries>
<r val="rval1"/>
<r val="rval2"/>
</r_entries>
</entry>

The XSLT operates using a for-each for entries, and needs to do all
combinations of [k] and [r] values. In non-XSL format I'd like to do the
following:

counter = 1;
foreach (entry in document)
foreach (k in entry)
foreach (r in entry)
(create a SQL like with the values of [counter/k/r])
(increment the counter by one)
/foreach
/foreach
/foreach

I'm not sure how to make this work in XSLT.

- Mike
Jul 20 '05 #2


something like

<xsl:for-each select="entry">
<xsl:for-each select="k_entries/k">
<xsl:value-of name="k" select="."/>
<xsl:for-each select="../../r_entries/r">
<xsl:variable name="n">
<xsl:number level="any" count="k|r"/>
</xsl:variable>
do something with . $k and $n
..

David
Jul 20 '05 #3
David,
<xsl:for-each select="entry">
<xsl:for-each select="k_entries/k">
<xsl:value-of name="k" select="."/>
<xsl:for-each select="../../r_entries/r">
<xsl:variable name="n">
<xsl:number level="any" count="k|r"/>
</xsl:variable>
do something with . $k and $n
..


Sadly, that'd only maintain the count inside an entry. this would still
leave the matter of maintaining the count for the whole document. for
instance, a document like

<doc>
<entry>
<k_entries><k val="ka"/><k val="kb"/></k_entries>
<r_entries><r val=ra"/></r_entries>
</entry>
<entry>
<k_entries><k val="kc"/></k_entries>
<r_entries><r val=rb"/><r val=rc"/><r val=rd"/></r_entries>
</entry>
<entry>
<k_entries><k val="kd"/></k_entries>
<r_entries><n val=re"/></r_entries>
</entry>
</doc>

Would have to end up looking like the following text:

insert into entry_table (id,k,r) values (1, ka, ra);
insert into entry_table (id,k,r) values (2, kb, ra);
insert into entry_table (id,k,r) values (3, kc, rb);
insert into entry_table (id,k,r) values (4, kc, rc);
insert into entry_table (id,k,r) values (5, kc, rd);
insert into entry_table (id,k,r) values (6, kd, re);

Know of any way to maintain a counter that creates these 'id' values
correctly?

- Mike
Jul 20 '05 #4
Sadly, that'd only maintain the count inside an entry.
No, if you wanted that you'd have to add from="entry" the default is the
whole document.
Know of any way to maintain a counter that creates these 'id' values
correctly?


As I posted.

David
Jul 20 '05 #5

I wrote
Sadly, that'd only maintain the count inside an entry.
No, if you wanted that you'd have to add from="entry" the default is the
whole document.


This is true.

Know of any way to maintain a counter that creates these 'id' values
correctly?


As I posted.

That is true as written, but not entirely helpful as xsl:number counts
the input tree (in this case the sum of the number of k and r nodes)
but you want the count in the output (essentially the product in this
case)

Your original post indicated that actually you just need a unique
identifier rather than a count, that's easier in xslt, the default mode
in the code below produces
[81732,kval1,rval1][d0e3d0e10d0e17]
[81732,kval1,rval2][d0e3d0e10d0e19]
[81732,kval2,rval1][d0e3d0e12d0e17]
[81732,kval2,rval2][d0e3d0e12d0e19]
[81732,kval1,rval1][d0e23d0e30d0e37]
[81732,kval1,rval2][d0e23d0e30d0e39]
[81732,kval2,rval1][d0e23d0e32d0e37]
[81732,kval2,rval2][d0e23d0e32d0e39]

on

<entries>
<entry>
<seq_num>81732</seq_num>
<k_entries>
<k val="kval1"/>
<k val="kval2"/>
</k_entries>
<r_entries>
<r val="rval1"/>
<r val="rval2"/>
</r_entries>
</entry>
<entry>
<seq_num>81732</seq_num>
<k_entries>
<k val="kval1"/>
<k val="kval2"/>
</k_entries>
<r_entries>
<r val="rval1"/>
<r val="rval2"/>
</r_entries>
</entry>
</entries>
which has a duplicated entry element.
You'll see the first [] on each line iterates twice through the k and r
values, but the second [] on each line is unique.

If you do need a count you have to work (a bit) harder. as shown in mode
b which passes the "count so far" as a parameter to the template for
entry. so in this case you get

[81732,kval1,rval1][1]
[81732,kval1,rval2][2]
[81732,kval2,rval1][3]
[81732,kval2,rval2][4]
[81732,kval1,rval1][5]
[81732,kval1,rval2][6]
[81732,kval2,rval1][7]
[81732,kval2,rval2][8]
David
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"


<xsl:template match="entries">
<xsl:apply-templates select="entry"/>
<xsl:apply-templates mode="b" select="entry[1]"/>
</xsl:template>

<xsl:template match="entry">
<xsl:variable name="e" select="."/>
<xsl:for-each select="k_entries/k">
<xsl:variable name="k" select="."/>
<xsl:for-each select="../../r_entries/r">
[<xsl:value-of select="concat($e/seq_num,',',$k/@val,',',@val,'][',generate-id($e),generate-id($k),generate-id(.),']')"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>

<xsl:template match="entry" mode="b">
<xsl:param name="c" select="0"/>
<xsl:variable name="e" select="."/>
<xsl:variable name="nr" select="count(r_entries/r)"/>
<xsl:for-each select="k_entries/k">
<xsl:variable name="k" select="."/>
<xsl:variable name="kp" select="position()"/>
<xsl:for-each select="../../r_entries/r">
[<xsl:value-of select="concat($e/seq_num,',',$k/@val,',',@val,'][',$c+($kp -1)*$nr + position(),']')"/>
</xsl:for-each>
</xsl:for-each>
<xsl:apply-templates select="following-sibling::entry[1]" mode="b">
<xsl:with-param name="c" select="$c + $nr * count(k_entries/k)"/>
</xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>
Jul 20 '05 #6

"M.Kamermans" <mk******@science.uva.nl> wrote in message
news:Xn*********************************@213.75.12 .135...
To be more specific, I have an XML document consisting of entries roughly
like this:

<entry>
<seq_num>81732</seq_num>
<k_entries>
<k val="kval1"/>
<k val="kval2"/>
</k_entries>
<r_entries>
<r val="rval1"/>
<r val="rval2"/>
</r_entries>
</entry>

The XSLT operates using a for-each for entries, and needs to do all
combinations of [k] and [r] values. In non-XSL format I'd like to do the
following:

counter = 1;
foreach (entry in document)
foreach (k in entry)
foreach (r in entry)
(create a SQL like with the values of [counter/k/r])
(increment the counter by one)
/foreach
/foreach
/foreach

I'm not sure how to make this work in XSLT.

- Mike

Here's a quick XSLT 2.0 + FXSL solution:

This transformation:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="f xs" <xsl:import href="../f/func-standardXpathFunctions.xsl"/>
<xsl:import href="../f/func-map.xsl"/>

<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
<xsl:for-each select=
"for $indEntry in 1 to count(/*/entry),
$ind-r_entry in 1 to count(/*/entry[$indEntry]/r_entries/r)
return
f:map(f:insert-before(data(/*/entry[$indEntry]/r_entries/r[$ind-r_entry]/@val),1),
data(/*/entry[$indEntry]/k_entries/*/@val)
) "


<xsl:value-of select="if(position() mod 2 = 1) then
(position() + 1) idiv 2,
', ', ., ', '
else
(. , '&#xA;')
"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

when applied on this source xml document:

<cat>
<entry>
<seq_num>81732</seq_num>
<k_entries>
<k val="kval1"/>
<k val="kval2"/>
</k_entries>
<r_entries>
<r val="rval1"/>
<r val="rval2"/>
</r_entries>
</entry>
<entry>
<seq_num>81742</seq_num>
<k_entries>
<k val="kval3"/>
<k val="kval4"/>
</k_entries>
<r_entries>
<r val="rval3"/>
<r val="rval4"/>
</r_entries>
</entry>
<entry>
<seq_num>81752</seq_num>
<k_entries>
<k val="kval5"/>
<k val="kval6"/>
</k_entries>
<r_entries>
<r val="rval5"/>
<r val="rval6"/>
</r_entries>
</entry>
</cat>

produces the desired result:

1 , kval1 , rval1
2 , kval2 , rval1
3 , kval1 , rval2
4 , kval2 , rval2
5 , kval3 , rval3
6 , kval4 , rval3
7 , kval3 , rval4
8 , kval4 , rval4
9 , kval5 , rval5
10 , kval6 , rval5
11 , kval5 , rval6
12 , kval6 , rval6

Cheers,

Dimitre Novatchev
Jul 20 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: inquirydog | last post by:
Hi- Does anyone know a way to compare whether two nodes contain the same information in xslt (the name, attributes, and all content recursivly should be the same. I am interested in the case...
1
by: karthigan | last post by:
I am writing a simple hardware test program in C that would run from Windows command line. Inside one of the loops, I have this code fragment that would display the Iteration count. { .......
1
by: cameron | last post by:
I am attempting to pass in an XmlDocument as a parameter to a transform: from my sample ASPX page: string BaseDir = "/cameron/Play/ComplexParam/"; XmlDocument XSL = new XmlDocument();...
6
by: Michiel Kamermans | last post by:
Hi, I need to generate a list based on a sorted nodeset, except duplicates need to be discarded. I initially though of doing a sort on a nodeset and then passing it to a template that iterates...
4
by: gualtmacchi | last post by:
I'm processing an XML input file getting a plain text file where from M nodes I got N output lines... It's not relevant but the input file is a recordset coming from a database and the output is...
1
by: jrwarwick | last post by:
Hello, I believe I have uncovered a bug in the .Net XSLT engine to do with 'for' loops in XSLT. Here are the steps to reproduce it: -Create A new webform project. -Add the xml file...
2
by: Adam dR. | last post by:
I have an xml file similar to: <menu> <menuitem name="home" show="false"/> <menuitem name="about" show="true"/> <menuitem name="links" show="true"/> <menuitem name="games" show="true"/>...
4
by: shaun roe | last post by:
I should like to count the frequency of strings embedded in a longer string, space separated. Specifically, I have: <phiModule> 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 8 5 5 5 6 6 6 7 7 7 7 7 7 7 7...
0
by: Leira | last post by:
Hi, I have a problem with grouping. My source XML has <record> elements that have a @name and a @group attribute. It looks something like this: <root> <result> <record name="test1"...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.