Reduce repeating expression in XSLT 1.0
I have the following XML (simplification):
<?xml version="1.0" encoding="utf-8"?>
<TestCases>
<TestCase>
<Name>Test1</Name>
<Result>Failed</Result>
<Properties>
<Type>Type1</Type>
</Properties>
</TestCase>
<TestCase>
<Name>Test1</Name>
<Result>Failed</Result>
<Properties>
<Type>Type2</Type>
</Properties>
</TestCase>
<TestCase>
<Name>Test1</Name>
<Result>Passed</Result>
<Properties>
<Type>Type1</Type>
</Properties>
</TestCase>
</TestCases>
I am interested to create a table that counts the number of passed/failed test cases, according to their type, like so:
Passed (Type1): 1 Failed (Type1): 1 Passed (Other types): 0 Failed (Other types): 1
To do that I am writing the following query:
<xsl:value-of select="count(//TestCase[Result = 'Passed' and count(Properties/TestType='Type1')>0])"/>
<xsl:value-of select="count(//TestCase[Result = 'Failed' and count(Properties/TestType='Type1')>0])"/>
<xsl:value-of select="count(//TestCase[Result = 'Passed' and count(Properties/TestType='Type1')=0])"/>
<xsl:value-of select="count(//TestCase[Result = 'Failed' and count(Properties/TestType='Type1')=0])"/>
As you can see, there is a LOT of code repetition going and would be great if I could save some of it. I understand that in XSL 2.0 I could use user functions for it, but what should I do in XSL 1.0? Do you see any options y开发者_如何学编程ou can see to optimize the repeating expressions?
P.S Note that is a simplifications of the real and while the expression doesn't seem long here, in the real code it is quite longer so the need is quite real.
Thanks!
Try:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="byType" match="Properties/Type" use="."/>
<xsl:template match="text()" />
<xsl:template match="Type[count(.|key('byType',.)[1])=1]">
<xsl:value-of select="concat(' Passed (',.,'): ',
count(key('byType',.)[../../Result='Passed']),
' Failed (',.,'): ',
count(key('byType',.)[../../Result='Failed']))" />
</xsl:template>
</xsl:stylesheet>
And you get:
Passed (Type1): 1 Failed (Type1): 1 Passed (Type2): 0 Failed (Type2): 1
Edit: less verbose.
In addition to the excellent solution bu @Alejandro using the Muenchian method for grouping, here is one that illustrates the use of variables:
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="vPassed"
select="/*/*[Result = 'Passed']"/>
<xsl:variable name="vFailed"
select="/*/*[Result = 'Failed']"/>
<xsl:template match="/">
<xsl:value-of select=
"concat('Passed (Type1): ',
count($vPassed[Properties/Type='Type1']),
' Failed (Type1): ',
count($vFailed[Properties/Type='Type1']),
' Passed (Other types): ',
count($vPassed[not(Properties/Type='Type1')]),
' Failed (Other types): ',
count($vFailed[not(Properties/Type='Type1')])
)
"/>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<TestCases>
<TestCase>
<Name>Test1</Name>
<Result>Failed</Result>
<Properties>
<Type>Type1</Type>
</Properties>
</TestCase>
<TestCase>
<Name>Test1</Name>
<Result>Failed</Result>
<Properties>
<Type>Type2</Type>
</Properties>
</TestCase>
<TestCase>
<Name>Test1</Name>
<Result>Passed</Result>
<Properties>
<Type>Type1</Type>
</Properties>
</TestCase>
</TestCases>
produces the wanted, correct result:
Passed (Type1): 1 Failed (Type1): 1 Passed (Other types): 0 Failed (Other types): 1
精彩评论