我有一个返回XML数据的函数,并希望为它编写测试以检查它是否返回预期的结果。 XML数据如下所示:
<Session Id="OF1qxev4OSZcIbsS">
<User Id="10001">
<LoginName>SelfTest</LoginName>
<RealName>SelfTest User</RealName>
</User>
<StartTime>2015-11-13T13:01:59Z</StartTime>
<EndTime>2015-11-13T15:01:59Z</EndTime>
</Session>
XML包含每个请求不同的数据,因此在与预期结果进行比较之前,我使用XSLT将某些固定模式替换为可变数据(会话ID属性和StartTime / EndTime节点的内容)。 XSL文件如下所示:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="no"/>
<xsl:variable name="uid-chars">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789</xsl:variable>
<xsl:variable name="uid-mask" >IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII</xsl:variable>
<xsl:variable name="timestamp-nums">0123456789</xsl:variable>
<xsl:variable name="timestamp-mask">DDDDDDDDDD</xsl:variable>
<xsl:template match="*">
<xsl:copy>
<!-- copy attributes -->
<xsl:apply-templates select="@*"/>
<!-- copy child elements -->
<xsl:apply-templates select="*|text()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<!-- trim whitespace -->
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
<!-- normalize uids -->
<xsl:template match="@Id">
<xsl:copy>
<xsl:attribute name="Id">
<xsl:value-of select="translate(., $uid-chars, $uid-mask)"/>
</xsl:attribute>
</xsl:copy>
</xsl:template>
<xsl:template match="StartTime|EndTime">
<xsl:copy>
<xsl:apply-templates mode="timestamp"/>
</xsl:copy>
</xsl:template>
<!-- normalize timestamps -->
<xsl:template mode="timestamp" match="text()">
<xsl:value-of select="translate(., $timestamp-nums, $timestamp-mask)"/>
</xsl:template>
</xsl:stylesheet>
预期的输出看起来像这样:
<Session Id="IIIIIIIIIIIIIIII">
<User Id="10001">
<LoginName>SelfTest</LoginName>
<RealName>SelfTest User</RealName>
</User>
<StartTime>DDDD-DD-DDTDD:DD:DDZ</StartTime>
<EndTime>DDDD-DD-DDTDD:DD:DDZ</EndTime>
</Session>
不幸的是,当前XSL高于规范化仅适用于StartTime / EndTime值,但不适用于会话ID:
<Session Id="OF1qxev4OSZcIbsS">
<User Id="10001">
<LoginName>SelfTest</LoginName>
<RealName>SelfTest User</RealName>
</User>
<StartTime>DDDD-DD-DDTDD:DD:DDZ</StartTime>
<EndTime>DDDD-DD-DDTDD:DD:DDZ</EndTime>
</Session>
将translate()函数应用于属性值的正确方法是什么?
注意:我在测试中使用了MSXML6中的XSLT引擎。
答案 0 :(得分:2)
您不应在模板中使用xsl:copy
与Id
属性匹配,因为它只是按原样复制属性。您的现有xsl:attribute
只是被忽略,因为您无法在此复制的属性中添加属性。
只需从模板中删除xsl:copy
,然后只需创建一个全新属性
<xsl:template match="@Id">
<xsl:attribute name="Id">
<xsl:value-of select="translate(., $uid-chars, $uid-mask)"/>
</xsl:attribute>
</xsl:template>
请注意,这会更新Id
元素的User
以及Session
元素。如果您确实希望将其限制为Session
属性,则可以改为使用这两个模板:
<xsl:template match="Session/@Id">
<xsl:attribute name="Id">
<xsl:value-of select="translate(., $uid-chars, $uid-mask)"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="@Id">
<xsl:copy />
</xsl:template>