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

谢谢

4

3 回答 3

3

为什么不简单:

<xsl:template match="@created_at">
    <xsl:attribute name="created_at">
        <xsl:value-of select="substring(translate(., 'T', ' '), 1, 19)" />
    </xsl:attribute>
</xsl:template>

xsl:copy注意:如果要更改属性的值,则不能使用。

于 2016-12-16T18:05:16.490 回答
2

从您的帖子中,听起来您所需要的只是简单的字符串处理。

为什么你的代码没有按照你想要的方式工作

您正在@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">指令。

一种有效的不同方法

而不是 using <xsl:copy>,您需要改为 use<xsl:attribute>以一种您还可以指定值的方式创建属性。在这种情况下,您已经知道要创建的属性的名称,因此您可以将名称值硬编码为created_at. 对于更灵活的方法,您可以改为将 name 值指定为{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。

于 2016-12-16T18:12:11.630 回答
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>
于 2016-12-16T17:37:32.110 回答