如何将 translate() 应用于 XSLT 中的属性值?
How can I apply translate() to an attribute value in XSLT?
我有一个 returns XML 数据的函数,我想为它编写一个测试来检查它是否 returns 预期的结果。 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 引擎。
您不应在与 Id
属性匹配的模板中使用 xsl:copy
,因为那样只会按原样复制属性。您现有的 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>
请注意,这将通过 User
元素的 Id
以及 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>
我有一个 returns XML 数据的函数,我想为它编写一个测试来检查它是否 returns 预期的结果。 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 引擎。
您不应在与 Id
属性匹配的模板中使用 xsl:copy
,因为那样只会按原样复制属性。您现有的 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>
请注意,这将通过 User
元素的 Id
以及 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>