添加参数化XML子元素取决于XSLT的变量值

时间:2016-05-09 06:38:00

标签: xml xslt junit

这是我的XML文件

<Results>
 <Fail>
    <Case>Test case name 1</Case>
    <Case>Test case name 2</Case>
 </Fail>
 <Pass>
    <Case>Test case name 3</Case>
    <Case>Test case name 4</Case>
  </Pass>
</Results>

这是预期的输出

<testsuites>
      <testcase classname="" name="Test case name 1" time="0.006">
         <failure message="test failure">Assertion failed</failure>
      </testcase>
      <testcase classname="" name="Test case name 2" time="0.006">
         <failure message="test failure">Assertion failed</failure>
      </testcase>
      <testcase classname="" name="Test case name 3" time="0" />
      <testcase classname="" name="Test case name 4" time="0" />
  </testsuite>

如果测试失败,则需要添加一个子元素,如预期结果所示。这是我创建的XSLT。我给了我意想不到的输出。有人可以帮助我实现这一目标。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="Results">
        <testsuites>
            <xsl:for-each select="Fail">
                <xsl:apply-templates select="Case">
                    <xsl:with-param name="teststatus" select="'Failed'"/>
                </xsl:apply-templates>
            </xsl:for-each>
            <xsl:for-each select="Pass">
                <xsl:apply-templates select="Case">
                    <xsl:with-param name="teststatus" select="'Passed'"/>
                </xsl:apply-templates>
            </xsl:for-each>
        </testsuites>
    </xsl:template> 
    <xsl:param name="failure_element">
      <failure type="fail"></failure>
    </xsl:param>    
    <xsl:template match="Case">
        <xsl:param name="teststatus"/>
        <testcase>
            <xsl:attribute name="classname">
                <xsl:value-of select="normalize-space(classname)" />
            </xsl:attribute>
            <xsl:attribute name="name">
                <xsl:value-of select="normalize-space()" />
            </xsl:attribute>
        <xsl:if test="$teststatus='Fail'">            
            <xsl:copy>              
                <xsl:copy-of select="$failure_element"/>
            </xsl:copy>       
        </xsl:if>       
        </testcase>     
    </xsl:template> 
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

这是一个使用&#34; push&#34;的XSLT2版本。处理(让XSLT引擎驱动进程)。请注意,没有任何for-each标记:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <testsuites>
            <xsl:apply-templates select="//Case" />
        </testsuites>
    </xsl:template>

    <xsl:template match="Case">
        <xsl:variable name="failed" select="name(..)='Fail'"/>
        <testcase classname="" name="{text()}" time="{if ($failed) then '0.000' else '0'}">
            <xsl:if test="$failed">
                <failure message="test failure">Assertion failed</failure>
            </xsl:if>
        </testcase>
    </xsl:template>
</xsl:stylesheet>

如果您需要XSLT1,则需要做的就是将条件表达式(if ... then ... else)移出另一个变量声明。

答案 1 :(得分:1)

这里是XSLT 1.0版本。 clasename和时间只是虚拟值,因为我认为应该做更多的事情然后设置它取决于失败。

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes" />

    <xsl:template match="/Results">
        <testsuites>
            <xsl:apply-templates select="//Case"/>
        </testsuites>
    </xsl:template>

    <xsl:template match="Case">
        <xsl:variable name="classname" select="''" /> 
        <xsl:variable name ="time" select="0" />

        <testcase classname="{$classname}" name="{.}" time="{$time}" >
            <xsl:if test="../self::Fail" >
                <failure message="test failure">Assertion failed</failure>
            </xsl:if>
        </testcase>
    </xsl:template>

</xsl:stylesheet>