XSLT:按值分组

时间:2012-06-25 14:39:06

标签: xml xslt

我想在整数='4'时使用xslt对下面的xml进行分组,然后循环遍历每个dict,检查每个元素是否有整数= 5然后变量应该设置为仅传递。如果有的话整数值为7,状态为失败。

有什么建议吗?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList1.0.dtd">
<plist version="1.0">
<dict>
<key>All Samples</key>
<array>
<dict>
<key>LogType</key>
<string>Start</string>
<key>Message</key>
<string>START:Certificate and Genre filter tests</string>
<key>Timestamp</key>
<date>2012-06-25T10:49:02Z</date>
<key>Type</key>
<integer>4</integer>
</dict>
<dict>
<key>LogType</key>
<string>Pass</string>
<key>Message</key>
<string>Navigation title bar should contain genre in card view : ACTION &amp; ADVENTURE</string>
<key>Timestamp</key>
<date>2012-06-25T10:49:13Z</date>
<key>Type</key>
<integer>5</integer>
</dict>
<dict>
<key>LogType</key>
<string>Pass</string>
<key>Message</key>
<string>START: certificate tests filter tests</string>
<key>Timestamp</key>
<date>2012-06-25T10:49:02Z</date>
<key>Type</key>
<integer>4</integer>
</dict>
<dict>
<key>LogType</key>
<string>Pass</string>
<key>Message</key>
<string>Navigation title bar should contain genre in card view : ACTION &amp; ADVENTURE</string>
<key>Timestamp</key>
<date>2012-06-25T10:49:13Z</date>
<key>Type</key>
<integer>5</integer>
</dict>
<dict>
<key>LogType</key>
<string>Fail</string>
<key>Message</key>
<string>Navigation title bar should contain genre in card view : ACTION &amp; ADVENTURE</string>
<key>Timestamp</key>
<date>2012-06-25T10:49:13Z</date>
<key>Type</key>
<integer>7</integer>
</dict>
</array>
</dict>
</plist>

expected result  in table view with format


| Test Name | test steps |   Test result|
START : GENRE FILTER TEST |    | FAIL ( background color to red)
test step1 | Navigation title bar should contain genre in card view | PASS
test step2 | Navigation title bar should contain genre in card view | FAIL

|START : certificate tests filter tests |    | PASS ( background color to green)
|test step 1 | Navigation title bar should contain genre in card view | PASS

感谢, 鲍勃

1 个答案:

答案 0 :(得分:0)

实现这一目标的一种方法是定义一个键,通过第一个前一个兄弟用整数= 4来查找 dict 元素

<xsl:key 
   name="test" 
   match="dict[integer[preceding-sibling::key[1]='Type']!=4]" 
  use="generate-id(
       preceding-sibling::dict[integer[preceding-sibling::key[1]='Type']=4][1]
    )" />

然后,您将首先将所有 dict 元素与integer = 4

匹配
<xsl:apply-templates 
   select="dict
     [key='All Samples']/array/dict[integer[preceding-sibling::key[1]='Type']=4]" />

然后你可以为模板写一个模板,其中存在'Fail'元素,并相应地处理它们

<xsl:template 
   match="dict
     [key('test', generate-id())[string[preceding-sibling::key[1]='LogType']='Fail']]">

所有其他匹配的 dict 元素都是成功元素。

然后在每个单独的测试中输出结果,你可以在键中查找它们

<xsl:apply-templates select="key('test', generate-id())" mode="results" />

请注意,模式是必需的,因为您将有多个匹配 dict 元素的模板,因此您需要区分它们。

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes"/>
   <xsl:key name="test" match="dict[integer[preceding-sibling::key[1]='Type']!=4]" use="generate-id(preceding-sibling::dict[integer[preceding-sibling::key[1]='Type']=4][1])"/>

   <xsl:template match="plist">
      <xsl:variable name="dicts" select="dict[key='All Samples']/array/dict[integer[preceding-sibling::key[1]='Type']=4]"/>       
      <table>
         <tr>
            <td>
               <xsl:text>Test Name</xsl:text>
            </td>
            <td>
               <xsl:text>Test Steps</xsl:text>
            </td>
            <td>
               <xsl:text>Test Result</xsl:text>
            </td>
         </tr>
      <xsl:apply-templates select="$dicts"/>
      </table>
      <xsl:variable name="fails" select="count($dicts[key('test', generate-id())[string[preceding-sibling::key[1]='LogType']='Fail']])" />
      <xsl:value-of select="concat('total tests passed = ', count($dicts) - $fails)" />
      <br />
      <xsl:value-of select="concat('total tests failed = ', $fails)" /> 
   </xsl:template>

   <xsl:template match="dict[key('test', generate-id())[string[preceding-sibling::key[1]='LogType']='Fail']]">
      <xsl:call-template name="dict">
         <xsl:with-param name="type" select="'Fail'"/>
         <xsl:with-param name="colour" select="'#FF0000'" />
      </xsl:call-template>
   </xsl:template>

   <xsl:template match="dict" name="dict">
      <xsl:param name="type" select="'Pass'"/>
      <xsl:param name="colour" select="'#00FF00'" />
      <tr>
         <td>
            <xsl:value-of select="string[preceding-sibling::key[1]='Message']"/>
         </td>
         <td>
         </td>
         <td style="background-color:{$colour}">
            <xsl:value-of select="$type"/>
         </td>
      </tr>
      <xsl:apply-templates select="key('test', generate-id())" mode="results" />
   </xsl:template>

   <xsl:template match="dict" mode="results">
      <tr>
         <td>
            <xsl:value-of select="concat('Test Step ', position())" />
         </td>
         <td>
            <xsl:value-of select="string[preceding-sibling::key[1]='Message']"/>
         </td>
         <td>
            <xsl:value-of select="string[preceding-sibling::key[1]='LogType']"/>
         </td>
      </tr>
   </xsl:template>
</xsl:stylesheet>

应用于XML示例时,输出以下内容

<table>
  <tr>
     <td>Test Name</td>
     <td>Test Steps</td>
     <td>Test Result</td>
  </tr>
  <tr>
     <td>START:Certificate and Genre filter tests</td>
     <td/>
     <td style="background-color:#00FF00">Pass</td>
  </tr>
  <tr>
     <td>Test Step 1</td>
     <td>Navigation title bar should contain genre in card view : ACTION &amp; ADVENTURE</td>
     <td>Pass</td>
  </tr>
  <tr>
     <td>START: certificate tests filter tests</td>
     <td/>
     <td style="background-color:#FF0000">Fail</td>
  </tr>
  <tr>
     <td>Test Step 1</td>
     <td>Navigation title bar should contain genre in card view : ACTION &amp; ADVENTURE</td>
     <td>Pass</td>
  </tr>
  <tr>
     <td>Test Step 2</td>
     <td>Navigation title bar should contain genre in card view : ACTION &amp; ADVENTURE</td>
     <td>Fail</td>
  </tr>
</table>
total tests passed = 1 
<br/>
total tests failed = 1 

请注意使用命名模板来为“成功”和“失败”行使用共享代码。