Subject: RE: [xsl] find first occurrence of attribute value grouped by element From: "Andrew Welch" <awelch@xxxxxxxxxxxxxxx> Date: Mon, 23 Sep 2002 17:05:29 +0100 |
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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] find first occurrence of , James Fuller | Thread | [xsl] hardware xml / xslt, jdgarrett |
RE: [xsl] xsl for parsing strange x, Passin,Thomas B. (To | Date | RE: [xsl] xsl for parsing strange x, Aparna Konduri |
Month |