属性的XSLT格式 - 日期

时间:2016-12-16 17:17:38

标签: java xml xslt formatdatetime

<?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错了吗?我找到了有关修改节点的文章,但没有找到属性。任何帮助将不胜感激。

谢谢

3 个答案:

答案 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。