XSL如何根据值计算节点数而不使用属性且不区分大小写

时间:2011-05-18 09:07:50

标签: xslt key

我最近开始研究XSL。我想用它来将我的xml文件转换为html文件。我想要提取的数据应该显示有多少节点具有一定的值。

XML具有以下结构:

<Tests> 
   <Test> 
        <TestName> a </TestName>  
        <Date> 12.11.10 </Date>       
        <Result> Pass</Result> 
   </Test>   
   <Test> 
       <TestName> b </TestName>      
       <Date> 13.11.10 </Date> 
       <Result> Fail </Result> 
   </Test>
    <Test>
        <TestName> c </TestName>         
        <Date> 14.11.10 </Date>     
        <Result> Pass </Result>   
    </Test>
</Tests> 

对于这个xml我输出为 - &gt; 2(通过次数)1(失败次数)

xsl用于上面的xml ::

<xsl:key name="kTestByResult" match="Test" use="normalize-space(Result)"/> 
<xsl:template match="/">         
 <xsl:value-of select="concat(count(key              
 ('kTestByResult','Fail')),' (number of Fails) ',
  count(key'kTestByResult','Pass')),'(number of Passes)')"/>     
 </xsl:template> 

这里的传球可能是(通过/传球/传球)。 在任何情况下,我都希望结果为2次传递。

任何给出一些想法???

3 个答案:

答案 0 :(得分:1)

将大小写字符翻译为小写:

<xsl:variable name="upper-case" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lower-case" select="'abcdefghijklmnopqrstuvwxyz'"/>

<xsl:key name="kTestByResult" match="Test" use="translate( normalize-space(Result), $upper-case, $lower-case )"/> 

<xsl:template match="/">         
    <xsl:value-of select="concat( 
        count( key('kTestByResult', 'fail') ), ' (number of Fails) ',
        count( key('kTestByResult', 'pass') ), '(number of Passes)'
    )"/>     
</xsl:template> 

答案 1 :(得分:1)

试试这个:

<xsl:key name="kTestByResult" match="Test" use="normalize-space(
  translate(Result,
  'qwertyuiopasdfghjklzxcvbnm',
  'QWERTYUIOPASDFGHJKLZXCVBNM'))"/> 

<xsl:template match="/">         
 <xsl:value-of select="concat(
   count(key('kTestByResult','FAIL')),
   ' (number of Fails) ',
   count(key('kTestByResult','PASS')),
   '(number of Passes)')"/>     
 </xsl:template> 

将所有值转换为大写,然后将大写的“PASS”或“FAIL”传递给键函数。

答案 2 :(得分:1)

这是一个更通用的解决方案,列出Result的所有不同值的计数而不对其进行硬编码 - 例如,如果更改了XML文档以便有结果SKIP或者INDECISIVE,这些新值也将被列出并计算在内:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vLower" select=
 "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vUpper" select=
 "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:key name="kResultByVal" match="Result"
  use="translate(normalize-space(),
                 'abcdefghijklmnopqrstuvwxyz',
                 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

 <xsl:template match="text()"/>

 <xsl:template match=
  "Result
   [generate-id()
   =
    generate-id(key('kResultByVal',
                     translate(normalize-space(),
                               'abcdefghijklmnopqrstuvwxyz',
                               'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                               )
                    )[1])
   ]
   ">
   <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select="translate(normalize-space(),$vLower,$vUpper)"/>
  <xsl:text>: </xsl:text>
  <xsl:value-of select=
   "count(key('kResultByVal',
              translate(normalize-space(),
                        $vLower,
                        $vUpper
                        )
              )
          )
   "/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<Tests>
    <Test>
        <TestName> a </TestName>
        <Date> 12.11.10 </Date>
        <Result> Pass</Result>
    </Test>
    <Test>
        <TestName> b </TestName>
        <Date> 13.11.10 </Date>
        <Result> Fail </Result>
    </Test>
    <Test>
        <TestName> c </TestName>
        <Date> 14.11.10 </Date>
        <Result> Pass </Result>
    </Test>
</Tests>

产生了想要的正确结果

PASS: 2
FAIL: 1

<强> II。产生相同结果的XSLT 2.0解决方案:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
     <xsl:for-each-group select="//Result"
                         group-by="normalize-space(upper-case(.))">
      <xsl:sequence select=
      "normalize-space(upper-case(.)),
       count(current-group()),
       '&#xA;'
      "/>
     </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>