Reputation: 15
I'm working in XSLT 1.0 right now, and I'm having trouble grouping correctly.My xml cannot be changed and it looks like:
<Analysis>
<comment>Test 1</comment>
<Action>
<Result>Passed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<comment>Start 2nd Phase</comment>
<Action>
<Result>Failed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<comment>Test 2</comment>
<Action>
<Result>Failed</Result>
</Action>
<Action>
<Result>Failed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<comment>Start 2nd Phase</comment>
<Action>
<Result>Failed</Result>
</Action>
<comment>Start 3rd Phase</comment>
<Action>
<Result>Failed</Result>
</Action>
<comment>Test 3</comment>
<Action>
<Result>Passed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<comment>Test 4</comment>
<Action>
<Result>Failed</Result>
</Action>
<Action>
<Result>Failed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
<comment>Start 2nd Phase</comment>
<Action>
<Result>Failed</Result>
</Action>
<Action>
<Result>Passed</Result>
</Action>
</Analysis>
The code I currently have will print a Failed if it finds a failed underneath the Test, but it only does it once. However, right now it does it underneath each comment, not each comment that has a "Test" in it.
<xsl:key name="actions" match="Action" use="generate-id(preceding-sibling::comment[1])" />
<xsl:template match="/Analysis">
<table>
<xsl:for-each select="comment">
<tr>
<td>
<xsl:if test="starts-with(text(),'Test')">
<xsl:value-of select="."/>
</xsl:if>
</td>
</tr>
<xsl:if test="key('actions', generate-id())[Result='Failed']">
<tr>
<td>Failed</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
Is there a way to make "preceding-sibling::comment[1]" work only for comments that start with "Test" or contain "Test"? There are a different number of non-important comments that are interspersed with the important information. Like with the example above, I want to see an output that would be like
Test 1
Failed
Test 2
Failed
Test 3
Test 4
Failed
However, with the code I currently have I get
Test 1
Failed
Test 2
Failed
Failed
Failed
Test 3
Test 4
Failed
Failed
Any help would be appreciated.
Upvotes: 1
Views: 69
Reputation: 52858
You should be able to add the predicate directly to the xsl:key
...
<xsl:key
name="actions"
match="Action"
use="generate-id(preceding-sibling::comment[starts-with(normalize-space(),'Test')][1])"
/>
I'd also remove the xsl:if
and put the test on the xsl:for-each
. That way you don't get blank rows for the comments you want to ignore.
Full example...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key
name="actions"
match="Action"
use="generate-id(preceding-sibling::comment[starts-with(normalize-space(),'Test')][1])"
/>
<xsl:template match="/Analysis">
<table>
<xsl:for-each select="comment[starts-with(normalize-space(),'Test')]">
<tr>
<td>
<xsl:value-of select="."/>
</td>
</tr>
<xsl:if test="key('actions', generate-id())[Result='Failed']">
<tr>
<td>Failed</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1