【问题标题】:How to test XSLT having multiple mode with XSpec?如何使用 XSpec 测试具有多种模式的 XSLT?
【发布时间】:2020-07-08 04:00:42
【问题描述】:

需要编写XSpec测试用例来测试XSLT,其中使用多种模式进行转换。 但是对于下面的测试用例,xspec 只测试应用默认模式的输出。 我想知道是否有办法测试转换的最终输出。

<!-- input.xml -->
<body>
 <div>
   <p class="Title"><span>My first title</span></p>
   <p class="BodyText"><span style="font-weight:bold">AAAAAAA</span><span>2 Jan 2020</span></p>
 </div>
</body>
<!-- conv.xsl -->
<xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

<!-- default mode : adding text-align attribute where @class=Title -->
<xsl:template match="*[ancestor::body]">
        <xsl:choose>
            <xsl:when test="@class = 'Title'">
                <xsl:element name="{local-name()}">
                    <xsl:copy-of select="@* except @style"/>
                    <xsl:attribute name="text-align" select="'center'"/>
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="{local-name()}">
                    <xsl:copy-of select="@*"/>
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

<!-- bodytext mode : changing element name to <title> where p[@class=Title] -->
<xsl:template match="p[@class]" mode="bodytext">
        <xsl:choose>
            <xsl:when test="@class = 'Title'">
                <title>
                    <xsl:copy-of select="@* except @class"/>
                    <xsl:apply-templates mode="bodytext"/>
                </title>
            </xsl:when>
            <xsl:otherwise>
              <para>
                    <xsl:apply-templates mode="bodytext"/>
              </para>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

<xsl:template match="body">
        <xsl:variable name="data">
            <body>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates/>
            </body>
        </xsl:variable>
        <xsl:apply-templates select="$data" mode="bodytext"/>
    </xsl:template>

<xsl:template match="node() | @*" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" mode="#current"/>
        </xsl:copy>
    </xsl:template>

O\P 第一个&lt;p&gt;:

-- 在 默认模式 应用后:&lt;p class="Title" text-align="center"&gt;。 [下面 xspec 测试这个 o\p]

-- 最终:&lt;title text-align="center"&gt;。 [想测试这个o\p]

<!-- test.xspec -->
<x:description xmlns:x="http://www.jenitennison.com/xslt/xspec" stylesheet="conv.xsl">
  <x:scenario label="XSS00001: Testing 'p[@class=Title]' converts to 'title'">
     <x:context href="input.xml" select="/body/div[1]/p[1]"/>
     <x:expect label="Testing 'p' converts to 'title'">
        <title text-align="center">
           <span>My first title</span>
        </title>
     </x:expect>
  </x:scenario>
</x:description>

这方面的任何建议都会有很大帮助。谢谢...

【问题讨论】:

  • 这是完整的 XSLT 吗?你在哪里使用命名模式?
  • @MartinHonnen :根据使用情况更新了 xsl 部分。谢谢

标签: unit-testing xslt xspec


【解决方案1】:

我不认为仅仅使用模式不能给你想要的结果。但是,按照您在 XSLT 中设置模式的方式,如果您在 XSpec 测试场景中匹配该 /body/div[1]/p[1],您将获得仅应用于该 p 元素的样式表。显然,对于 p*[ancestor::body] 在未命名模式下匹配,并且在该模式下处理停止,因为从该模板中永远不会使用其他模式。

因此,您可能需要将 body 元素设置为上下文并使用如下场景:

<x:scenario label="XSS00002: Testing 'p[@class=Title]' converts to 'title'">
    <x:context>
        <body>
            <div>
                <p class="Title">...</p>
                <p class="BodyText">...</p>
            </div>
        </body>
    </x:context>
    <x:expect label="Testing 'p' converts to 'title'">
        <body>
            <div>
                <title text-align="center">...</title>
                <para>...</para>
            </div>
        </body>
    </x:expect>
</x:scenario>

【讨论】:

  • 感谢您指出处理流程。但是,在 xslt 中设置模式的另一种方法是什么,以便 xspec 考虑最终的 o\p?
  • @sspsujit,XSpec 会考虑最终输出,但您的测试场景与仅转换 p 元素的最终结果相反,对于该 p 元素,您的代码仅创建一个 text-align 属性,它不会将元素从p 更改为title。要重新组织 XSLT,将模式分成两个不同的样式表模块并将它们导入第三个可能会有所帮助,然后为第一个样式表编写测试,第二个和最后一个导入两个模块。
【解决方案2】:

马丁说的很对。

另一种写法是:

  <x:scenario label="When a document contains 'body//p[@class=Title]'">
     <x:context href="input.xml" />
     <x:expect label="'p' is converted to 'title[@text-align]'"
               test="body/div/title">
        <title text-align="center">
           <span>My first title</span>
        </title>
     </x:expect>
  </x:scenario>

也就是说,

  • x:context 中删除@select,因为您和/或conv.xsl 似乎假定转换总是从文档节点(/) 开始。
  • @test 添加到x:expect,因为您似乎只对转换结果中的title 元素感兴趣。

【讨论】:

    猜你喜欢
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多