<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd created_at="2016-12-15T15:02:55Z">
<title created_at="2016-12-15T15:02:55Z">Empire Burlesque</title>
<artist created_at="2016-12-15T15:02:55Z">Bob Dylan</artist>
<cover created_at="2016-12-15T15:02:55Z"/>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
我想格式化所有出现的created_at属性
input format YYYY-MM-DDTHH:MM:SSZ
output format YYYY-MM-DD HH:MM:SS
我目前正在使用以下xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Edit dates to conform to dbunit format-->
<xsl:template match="@created_at">
<xsl:copy>
<xsl:call-template name="formatdate">
<xsl:with-param name="datestr" select="@created_at"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="formatdate">
<xsl:param name="datestr" />
<!-- input format YYYY-MM-DDTHH:MM:SSZ -->
<!-- output format YYYY-MM-DD HH:MM:SS -->
<xsl:variable name="datetext">
<xsl:value-of select="substring-before($datestr,'T')" />
</xsl:variable>
<xsl:variable name="timetext">
<xsl:value-of select="substring($datestr,12,18)" />
</xsl:variable>
<xsl:value-of select="concat($datetext, ' ', $timetext)" />
</xsl:template>
</xsl:stylesheet>
然而,当我通过转换xslt进行调试时,它似乎没有进入formatdate调用模板。我的xpath错了吗?我找到了有关修改节点的文章,但没有找到属性。任何帮助将不胜感激。
谢谢
答案 0 :(得分:2)
为什么不简单:
$null
注意:如果您想更改属性的值,则无法使用$_
。
答案 1 :(得分:1)
试试这个
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='xml' indent='yes'/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Edit dates to conform to dbunit format-->
<xsl:template match="@created_at">
<xsl:call-template name="formatdate">
<xsl:with-param name="datestr" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="formatdate">
<xsl:param name="datestr" />
<!-- input format YYYY-MM-DDTHH:MM:SSZ -->
<!-- output format YYYY-MM-DD HH:MM:SS -->
<xsl:variable name="datetext">
<xsl:value-of select="substring-before($datestr,'T')" />
</xsl:variable>
<xsl:variable name="timetext">
<xsl:value-of select="substring($datestr,12,8)" />
</xsl:variable>
<xsl:attribute name="created_at">
<xsl:value-of select="concat($datetext, ' ', $timetext)" />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
从你的帖子中,听起来你需要的只是简单的字符串处理。
您正在使用此模板处理@created_at
属性:
<xsl:template match="@created_at">
<xsl:copy>
<xsl:call-template name="formatdate">
<xsl:with-param name="datestr" select="@created_at"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
这里的踢球者是你正在使用<xsl:copy>
。与属性一起使用时,<xsl:copy>
会复制整个属性,名称和值。由于属性不能包含任何子节点,因此忽略了<xsl:copy>
指令的子节点 - 因此XSLT处理器永远不会评估<xsl:call-template name="formatdate">
指令。
您需要使用<xsl:copy>
来创建属性,而不是使用<xsl:attribute>
,您也可以指定值。在这种情况下,您已经知道要创建的属性的名称,因此您可以将名称值硬编码为created_at
。对于更灵活的方法,您可以将名称值赋予{name(.)}
- 这只是抓取正在处理的属性的名称,这与您可能认为<xsl:copy>
的行为更接近。 :)
也可以在单个xsl:value-of
表达式中生成所需的字符串,而不依赖于这么多变量。
<xsl:template match="@created_at">
<xsl:attribute name="{name(.)}">
<xsl:value-of select="concat(substring-before(., 'T'), ' ', substring-before(substring-after(., 'T'), 'Z'))"/>
</xsl:attribute>
</xsl:template>
分解select
声明:
concat()
将多个字符串拼接在一起。substring-before(., 'T')
抓取T
之前的所有内容 - 这是日期部分。' '
在中间添加了单个空格。substring-before(substring-after(., 'T'), 'Z')
-
substring-after(., 'T')
抓住T
之后的所有内容 - 这是时间部分。Z
,所以我们使用substring-before
作为外部表达来关闭它。不需要变量,它可以完成工作。确认使用XSLT 1.0。