[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: find first occurrence of attribute value grouped b

Subject: RE: find first occurrence of attribute value grouped by element
From: "Andrew Welch" <awelch@xxxxxxxxxxxxxxx>
Date: Mon, 23 Sep 2002 17:05:29 +0100
xslt find first element
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="{@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[@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="{@id}" Unit_id="{parent::testdata/@Unit_id}">
        <xsl:attribute name="pft">
        <xsl:choose>
          <xsl:when test="@passed = 'T' and
not(preceding-sibling::test[@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[@passed='T']" use="@id" />
> <xsl:key name="keyFailed" match="test[@passed='F']" use="@id" />
> 
> <!--  The key that follows must be incorrect...  :(   -->
> <xsl:key name="keyFRP" match="test[@passed='T' and
> not(preceding-sibling::*[@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@xxxxxxxxxxxx
> 
>  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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.