开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜