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

发布于 2024-11-08 14:38:06 字数 1171 浏览 0 评论 0原文

我最近开始学习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,我得到的输出为 --> 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 Passes。

有什么想法吗???

I have recently started to study XSL. I would like to use it to transform my xml file into html one. The data that I want to extract should present how many nodes have certain value.

XML has following structure:

<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> 

For this xml I got output as --> 2 (number of Passes) 1 (number of Fails)

xsl for the above 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> 

Here the pass might be (PASS/pass/Pass).
At any situation I want the result as 2 Passes.

any give some idea for this???

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

混吃等死 2024-11-15 14:38:06

将大写字符转换为小写:

<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> 

Translate up-case characters to low-case:

<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> 
烟若柳尘 2024-11-15 14:38:06

试试这个:

<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”传递给关键函数。

Try this:

<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> 

That'll convert all values to upper case, and then just pass the uppercase 'PASS' or 'FAIL' to the key function.

前事休说 2024-11-15 14:38:06

这是一个更通用的解决方案,它列出了 Result 的所有不同值的计数,而不对其进行硬编码 - 例如,如果 XML 文档发生更改,结果会被跳过或 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>
</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()),
       '
'
      "/>
     </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

This is a more general solution that lists the count of all distinct values of Result without hardcoding them -- for example, if the XML document is changed so that there are results SKIP or INDECISIVE, these new values will also be listed and counted:

<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>
</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>

when applied to the provided XML document:

<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>

the wanted, correct result is produced:

PASS: 2
FAIL: 1

II. An XSLT 2.0 solution that produces the same result:

<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()),
       '
'
      "/>
     </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文