Hi,
You could try the result-tree-fragment approach, which gives you an
easier time keeping track of whats going on. So, the following code
produces an rtf like this:
<test id="test1" Unit_id="000001" pft="yes"></test>
<test id="test2" Unit_id="000001" pft="yes"></test>
<test id="test1" Unit_id="000001" pft="no"></test>
....
You can then query into this using the node-set extension function,
locating the pft attribute (passed first time :) using the id's
provided.
To build this rtf, you need to create a variable as a top level element,
selecting all <test>'s within<testdata>
<xsl:variable name="tests">
<xsl:for-each select="//testdata/test">
...
</xsl:for-each>
</xsl:variable>
To makes things simple we then need to store the @id so we can compare
it to preceding-siblings, and populate the id attributes:
<xsl:variable name="tests">
<xsl:for-each select="//testdata/test">
<xsl:variable name="id" select="@id"/>
<test id="{(_at_)id}" Unit_id="{parent::testdata/@Unit_id}">
...
</test>
</xsl:for-each>
</xsl:variable>
For the pft attribute, you are basically saying 'if @passed = T and
there are no preceding siblings with @id the same as the current @id
with @passed, then yes otherwise no',
so,
<xsl:attribute name="pft">
<xsl:choose>
<xsl:when test="@passed = 'T' and not(preceding-sibling::test[(_at_)id =
$id]/@passed = 'T')">yes</xsl:when>
<xsl:otherwise>no</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
To put it all together:
<xsl:variable name="tests">
<xsl:for-each select="//testdata/test">
<xsl:variable name="id" select="@id"/>
<test id="{(_at_)id}" Unit_id="{parent::testdata/@Unit_id}">
<xsl:attribute name="pft">
<xsl:choose>
<xsl:when test="@passed = 'T' and
not(preceding-sibling::test[(_at_)id = $id]/@passed = 'T')">yes</xsl:when>
<xsl:otherwise>no</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</test>
</xsl:for-each>
</xsl:variable>
If you need help querying into the rtf then repost,
cheers
andrew
Hi,
This is my first posting to this list site. I have tried to search the
archives
and other sites to help with my problem, but have not found anything
which addresses it specifically. Please excuse my newbieness.
Problem:
Determine the first occurrence of a particular attribute
value grouped by
element.
Example data:
testdata.xml:
<?xml version="1.0" ?>
<!-- simplified test data example 1-->
<root>
<testdata Unit_id="000001">
<test id="test1" passed='F' timestamp="2002-09-01 12:00:00"></test>
<test id="test2" passed='T' timestamp="2002-09-01 13:00:00"></test>
<test id="test1" passed='T' timestamp="2002-09-02 11:00:00"></test>
</testdata>
<testdata Unit_id="000002">
<test id="test1" passed='T' timestamp="2002-09-01 10:00:00"></test>
<test id="test2" passed='T' timestamp="2002-09-01 13:00:00"></test>
<test id="test3" passed='T' timestamp="2002-09-02 11:00:00"></test>
</testdata>
<testdata Unit_id="000003">
<test id="test1" passed='T' timestamp="2002-09-03 10:00:00"></test>
<test id="test3" passed='T' timestamp="2002-09-04 14:00:00"></test>
<test id="test2" passed='F' timestamp="2002-09-02 11:00:00"></test>
</testdata>
</root>
Desired output:
--------------------------------------------------------------
--------------
----------------
Test Total Attempts Total Pass Total Fail Pass on
First Attempt
First Run Ratio
--------------------------------------------------------------
--------------
----------------
test 1 4 3 1 2
66.7%
test 2 4 2 2 1
25%
test 3 2 2 0 2
100%
My XSLT attempt at producing the listed output:
testdata.xsl:
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:key name="keyTest" match="test" use="@id" />
<xsl:key name="keyPassed" match="test[(_at_)passed='T']" use="@id" />
<xsl:key name="keyFailed" match="test[(_at_)passed='F']" use="@id" />
<!-- The key that follows must be incorrect... :( -->
<xsl:key name="keyFRP" match="test[(_at_)passed='T' and
not(preceding-sibling::*[(_at_)passed='F'])]" use="@id" />
<xsl:template match="/">
<html>
<head>
<title>Summary Report</title>
</head>
<body>
<table border="1">
<tr>
<th>Test</th>
<th>Total Attempts</th>
<th>Total Pass</th>
<th>Total Fail</th>
<th>Pass on First Attempt</th>
<th>First Run Ratio</th>
</tr>
<testdata>
<xsl:call-template name="summary_list" />
</testdata>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="//testdata//test[generate-id(.) =
generate-id(key('keyTest', @id))]" name="summary_list">
<xsl:for-each select = "//testdata//test[generate-id(.) =
generate-id(key('keyTest', @id))]" >
<!--<xsl:variable name="theTS" select="@id" />-->
<xsl:variable name="firstUnit" select="../@Unit_id" />
<tr>
<!-- Display the Test Name! -->
<td align="center"><b><xsl:value-of select = "@id" /></b></td>
<!-- Count all Tests! -->
<td align="center"><xsl:value-of select =
"count(key('keyTest',@id))"
/></td>
<!-- Count the Passes! -->
<td align="center"><xsl:value-of select =
"count(key('keyPassed',@id))"
/></td>
<!-- Count the Fails! -->
<td align="center"><xsl:value-of select =
"count(key('keyFailed',@id))"
/></td>
<!-- Try to Count the first pass! -->
<td align="center"><xsl:value-of select =
"count(key('keyFRP',@id))"
/></td>
<!-- Calculate First Run Ratio -->
<xsl:choose>
<xsl:when test="count(key('keyFRP',@id))">
<td align="right">
<xsl:value-of select =
"format-number(count(key('keyFRP',@id)) div
count(key('keyTest',@id)),'###.###%')" />
</td>
</xsl:when>
<xsl:otherwise>
<td align="right"><xsl:value-of select = "'0%'" /></td>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This XSLT file seemed to work for the first data example, but
the second example listed below failed to generate the proper results.
<?xml version="1.0" ?>
<!-- simplified test data example 2 -->
<root>
<testdata Unit_id="000001">
<test id="test1" passed='F' timestamp="2002-09-01 12:00:00"></test>
<test id="test2" passed='F' timestamp="2002-09-01 13:00:00"></test>
<test id="test1" passed='T' timestamp="2002-09-02 11:00:00"></test>
<test id="test2" passed='T' timestamp="2002-09-02 14:00:00"></test>
</testdata>
<testdata Unit_id="000002">
<test id="test1" passed='T' timestamp="2002-09-01 10:00:00"></test>
<test id="test2" passed='T' timestamp="2002-09-01 13:00:00"></test>
<test id="test3" passed='T' timestamp="2002-09-02 11:00:00"></test>
</testdata>
<testdata Unit_id="000003">
<test id="test1" passed='T' timestamp="2002-09-03 10:00:00"></test>
<test id="test3" passed='T' timestamp="2002-09-04 14:00:00"></test>
<test id="test2" passed='F' timestamp="2002-09-02 11:00:00"></test>
<test id="test4" passed='T' timestamp="2002-09-07 11:00:00"></test>
</testdata>
</root>
It did seem to work for the first data set, but it failed to work
correctly for the second data set!
I was thinking that if I counted the passes for a test for a
given unit_id
where a fail had not occurred, that this would give the
desired result.
I know that the key that I have created for the first pass occurrence
is not correct. The 'test4' is not counted as a first run
pass for some
reason. I am not sure what the proper key should be.
I had not used the timestamp data because I am assuming that
a fail will
not occur after a pass of a particular test, and that a test
would not
be taken after a pass had occurred.
What would the proper approach be to solve this problem?
Any help will be greatly appreciated!
Thanks,
John Pallister
jpallister(_at_)engenius(_dot_)com
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.391 / Virus Database: 222 - Release Date: 19/09/2002
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.391 / Virus Database: 222 - Release Date: 19/09/2002
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list