gpt4 book ai didi

xslt - 在 XSLT 1.0 中扩展日期时间范围

转载 作者:行者123 更新时间:2023-12-04 18:21:02 27 4
gpt4 key购买 nike

我有一个我想与之交互的日期的事件的 XML 提要。

源 XML:

<?xml version="1.0" encoding="UTF-8"?>
<events>
<event>
<!-- various elements -->
<start_datetime value="2012-02-09 10:00:00"/>
<end_datetime value="2012-02-09 11:00:00"/>
<!-- various elements -->
</event>
<event>
<!-- various elements -->
<start_datetime value="2012-02-09 10:00:00"/>
<end_datetime value="2012-02-10 15:00:00"/>
<!-- various elements -->
</event>
<!-- other events -->
</events>

请注意 /events/event[1]是在同一天开始和结束的事件; /events/event[2] ,另一方面,跨越两天。这是我想要完成的:
  • 对于同一天的事件,不要管日期时间,只需将这些属性转换为子元素。
  • 对于跨越多天的事件,我想创建多个 <event> (a) 与整个时间跨度相匹配和 (b) 在适当情况下跨越一整天的时间的元素。

  • 所以,我理想的 XSLT 会产生:

    所需的 XML:
    <?xml version="1.0" encoding="UTF-8"?>
    <events>
    <event>
    <!-- various elements -->
    <start_datetime>2012-02-09 10:00:00</start_datetime>
    <end_datetime>2012-02-09 11:00:00</end_datetime>
    <!-- various elements -->
    </event>
    <event>
    <!-- various elements -->
    <start_datetime>2012-02-09 10:00:00</start_datetime>
    <end_datetime>2012-02-09 23:59:59</end_datetime>
    <!-- various elements -->
    </event>
    <event>
    <!-- various elements -->
    <start_datetime>2012-02-10 00:00:00</start_datetime>
    <end_datetime>2012-02-10 15:00:00</end_datetime>
    <!-- various elements -->
    </event>
    <!-- other events -->
    </events>

    注意我的规则是如何得到满足的:
  • 因为/events/event[1]发生在同一天,我们不理会它(除了将属性值更改为子元素的琐碎任务)。
  • /events/event[2]跨越两天,这意味着它需要两个 <event> block (一个从开始日期时间到该日期晚上 11:59:59,一个从结束日期 00:00:00 到结束日期时间)。

  • 最终考虑:
  • 这需要在 XSLT 1.0 中完成。
  • 我不反对使用 EXSLT 的日期函数——但是,如果可以避免它们,那将是可取的。

  • 清如泥?一如既往,感谢您的帮助。 :)

    最佳答案

    这是一个 XSLT 1.0 解决方案,它不使用 EXSLT 日期函数,而是使用命名模板向给定日期添加一个,使用字符串操作函数从日期字符串中添加年、月和日

    <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>

    <xsl:template match="event" name="event">
    <xsl:param name="start_datetime" select="start_datetime/@value"/>
    <xsl:variable name="end_datetime" select="end_datetime/@value"/>
    <event>
    <xsl:apply-templates select="start_datetime/preceding-sibling::node()"/>
    <start_datetime>
    <xsl:value-of select="$start_datetime"/>
    </start_datetime>
    <end_datetime>
    <xsl:choose>
    <xsl:when test="substring($start_datetime, 1, 10) = substring($end_datetime ,1, 10)">
    <xsl:value-of select="$end_datetime"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="concat(substring($start_datetime, 1, 10), ' 23:59:59')"/>
    </xsl:otherwise>
    </xsl:choose>
    </end_datetime>
    <xsl:apply-templates select="end_datetime/following-sibling::node()"/>
    </event>
    <xsl:if test="substring($start_datetime, 1, 10) != substring($end_datetime ,1, 10)">
    <xsl:call-template name="event">
    <xsl:with-param name="start_datetime">
    <xsl:call-template name="addOneToDate">
    <xsl:with-param name="date" select="$start_datetime"/>
    </xsl:call-template>
    </xsl:with-param>
    </xsl:call-template>
    </xsl:if>
    </xsl:template>

    <xsl:template name="addOneToDate">
    <xsl:param name="date"/>
    <xsl:variable name="year" select="number(substring($date, 1, 4))"/>
    <xsl:variable name="month" select="number(substring($date, 6, 2))"/>
    <xsl:variable name="day" select="number(substring($date, 9, 2))"/>
    <xsl:variable name="daysInMonth">
    <xsl:choose>
    <xsl:when test="$month = 2">
    <xsl:choose>
    <xsl:when test="($year div 4 = 0 and $year div 100 != 0) or ($year div 400 = 0)">29</xsl:when>
    <xsl:otherwise>28</xsl:otherwise>
    </xsl:choose>
    </xsl:when>
    <xsl:when test="$month = 4 or $month = 6 or $month = 9 or $month = 11">30</xsl:when>
    <xsl:otherwise>31</xsl:otherwise>
    </xsl:choose>
    </xsl:variable>
    <xsl:choose>
    <xsl:when test="$day != $daysInMonth">
    <xsl:value-of select="concat($year, '-', format-number($month, '00'), '-', format-number($day + 1, '00'), ' 00:00:00')"/>
    </xsl:when>
    <xsl:when test="$month = 12">
    <xsl:value-of select="concat($year + 1, '-01-01 00:00:00')"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="concat($year, '-', format-number($month + 1, '00'), '-01 00:00:00')"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>
    </xsl:stylesheet>

    应用于您的示例 XML 时,将输出以下内容
    <events>
    <event>
    <!-- various elements -->
    <start_datetime>2012-02-09 10:00:00</start_datetime>
    <end_datetime>2012-02-09 11:00:00</end_datetime>
    <!-- various elements -->
    </event>
    <event>
    <!-- various elements -->
    <start_datetime>2012-02-09 10:00:00</start_datetime>
    <end_datetime>2012-02-09 23:59:59</end_datetime>
    <!-- various elements -->
    </event>
    <event>
    <!-- various elements -->
    <start_datetime>2012-02-10 00:00:00</start_datetime>
    <end_datetime>2012-02-10 15:00:00</end_datetime>
    <!-- various elements -->
    </event>
    <!-- other events -->
    </events>

    我相信你会同意使用 EXSLT 会更简单......

    关于xslt - 在 XSLT 1.0 中扩展日期时间范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10689099/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com