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 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
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
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 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
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>
"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
(. , '
')
"/>
</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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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.
{
.......
|
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();...
|
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...
|
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...
|
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...
|
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"/>...
|
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...
|
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"...
|
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...
|
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...
|
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...
|
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...
|
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)...
|
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...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
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
|
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...
| |