使用xsl解析xml输出,使用变量?

时间:2011-04-12 12:38:41

标签: html xml xslt xpath

我正在尝试解析googletest的xml文件输出,以便在html页面中以相当方式显示结果。我有一个公平的裂缝,并有一个有效的解决方案。只剩下一件事了。 目前每个类都有一个标题,每个函数+测试显示在下面,我正在寻找一种方法从xml属性中提取函数名称,使其成为自己的子标题。以下示例


当前输出

班级姓名
functionName_testName
functionName_test2Name
function2Name_testName

期望输出

班级姓名
functionName
测试名
test2Name
function2Name
testName

要解析的XML

<testsuite name="testPacketProcessor" tests="27" failures="0" disabled="0" errors="0" time="36.875">
    <testcase name="testInitialise_IpNotSet" status="run" time="0" classname="testPacketProcessor" />
    <testcase name="testInitialise_GoodIp" status="run" time="2.046" classname="testPacketProcessor" />
    <testcase name="testInitialise_BadIp" status="run" time="0.032" classname="testPacketProcessor" />
</testsuite>

XSL目前已实施

<xsl:for-each select="testsuites/testsuite">
    <div class="testHeading">
        <span><xsl:value-of select="substring-after(@name,'test')"/></span>
    </div>
    <xsl:for-each select="testcase">
    <div class="testReport">
        <xsl:if test="not(starts-with(@name,'DISABLED'))"><xsl:value-of select="substring-after(@name,'test')"/></xsl:if>
        <xsl:if test="starts-with(@name,'DISABLED')"><xsl:value-of select="substring-after(@name,'DISABLED_test')"/></xsl:if>
        <xsl:text> - </xsl:text>
        <xsl:if test="starts-with(@status,'run')">
            <xsl:if test="failure"><xsl:text>Fail</xsl:text></xsl:if>
            <xsl:if test= "not(failure)"><xsl:text>Pass</xsl:text></xsl:if>
        </xsl:if>
        <xsl:if test="starts-with(@status,'not')"><xsl:text>Disabled</xsl:text></xsl:if>
    </div>
    </xsl:for-each>
</xsl:for-each>

使用上面的xml作为示例,我想在数据包处理器标题下添加“Initialise”子标题,每个测试都在子标题下进行

任何关于最佳方式的建议都将非常感激。我看过xsl变量,但无法理解如何处理无法更改值。还阅读了一些关于xsl模板和递归的内容,但我不确定这对于这种情况会有什么用。

提前致谢

Dougie

1 个答案:

答案 0 :(得分:1)

此转换生成每个测试用例的子标题和名称

<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:template match="testcase">
  Subheading: <xsl:value-of select=
   "substring-before(substring-after(@name, 'test'),
                     '_'
                     )
   "/>
   Name: <xsl:value-of select="substring-after(@name, '_')"/>
   <xsl:text>&#xA;</xsl:text>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<testsuites>
    <testsuite name="testPacketProcessor" tests="27" failures="0" disabled="0" errors="0" time="36.875">
        <testcase name="testInitialise_IpNotSet" status="run" time="0" classname="testPacketProcessor" />
        <testcase name="testInitialise_GoodIp" status="run" time="2.046" classname="testPacketProcessor" />
        <testcase name="testInitialise_BadIp" status="run" time="0.032" classname="testPacketProcessor" />
    </testsuite>
</testsuites>

产生了想要的正确结果

  Subheading: Initialise
   Name: IpNotSet

  Subheading: Initialise
   Name: GoodIp

  Subheading: Initialise
   Name: BadIp

解释:使用标准XPath函数substring-before()substring-after()

编辑:在评论中,OP明确表示他希望按功能进行分组(厌倦了不好的问题?):

此转换执行所需的分组:

<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:key name="kTestsByFunction" match="testcase"
     use="substring-before(substring-after(@name, 'test'),
                             '_'
                              )"
  />

    <xsl:template match=
     "testcase
     [generate-id()
   =
    generate-id(key('kTestsByFunction',
                    substring-before(substring-after(@name, 'test'),
                                     '_'
                                      )
                    )[1]
               )
      ]
     ">
    Subheading: 
        <xsl:value-of select=
        "substring-before(substring-after(@name, 'test'),
                          '_'
                          )
     "/>
    <xsl:for-each select=
     "key('kTestsByFunction',
           substring-before(substring-after(@name, 'test'),
                                '_'
                                )
         )
     ">
      Name:
           <xsl:value-of select="substring-after(@name, '_')"/>
           <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

并生成想要的结果

    Subheading: 
        Initialise
  Name:
           IpNotSet

  Name:
           GoodIp

  Name:
           BadIp