【问题标题】:Sorting XSL by date in Month-Name Day-Number Year-Number format以 Month-Name Day-Number Year-Number 格式按日期对 XSL 进行排序
【发布时间】:2015-10-02 07:31:28
【问题描述】:

我有一个 Joomla SobiPro 事件数据库,每个事件都包含一个名为“start_date”的日期字段,看起来像“2015 年 10 月 10 日”和“2016 年 1 月 3 日”。我需要搜索不同的字段(与给定邮政编码的距离(以英里为单位)),然后输出按这些日期升序排序的结果。

我对 XSL/SobiPro/Joomla 完全陌生,所以我很挣扎,但经过大量谷歌搜索后,我发现我需要在 SobiPro 模板中<!-- **** Insert Sort Command Here **** --> 指示的位置插入 XSL 排序命令文件 common/entries.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" encoding="UTF-8" />
        <xsl:include href="vcard.xsl" />
        <xsl:include href="manage.xsl" />

        <xsl:template name="entriesLoop">
                <xsl:variable name="entriesInLine">
                        <xsl:value-of select="entries_in_line" />
                </xsl:variable>

                <xsl:variable name="cellClass">
                        <xsl:value-of select="floor( 12 div $entriesInLine )" />
                </xsl:variable>

                <xsl:variable name="entriesCount">
                        <xsl:value-of select="count(entries/entry)" />
                </xsl:variable>

                <xsl:comment>entries loop - start</xsl:comment>
        <div class="entry-container">
                <xsl:for-each select="entries/entry">

<!-- **** Insert Sort Command Here **** -->

                    <xsl:if test="($entriesInLine > 1 and (position() = 1 or (position() mod $entriesInLine) = 1 )) or $entriesInLine = 1">
                        <!-- opening the "table" row -->
                        <xsl:text disable-output-escaping="yes">&lt;div class="row-fluid" &gt;</xsl:text>
                    </xsl:if>
                    <div class="span{$cellClass}">
                        <xsl:call-template name="vcard" />
                    </div>
                    <xsl:if test="($entriesInLine > 1 and ((position() mod $entriesInLine) = 0 or position() = $entriesCount)) or $entriesInLine = 1">
                        <!-- closing the "table" row -->
                        <xsl:text disable-output-escaping="yes">&lt;/div&gt;</xsl:text>
                    </xsl:if>
                </xsl:for-each>
        </div>
                <xsl:comment>entries loop - end</xsl:comment>

        </xsl:template>
</xsl:stylesheet>

我对 XSL 完全不熟悉,但我确实发现如果日期格式是 2015 10 09 而不是 Oct 09 2015,那么我可以将上面的注释行替换为以下行:

<xsl:sort select="fields/field_start_date" order="ascending" />

并且排序会成功,因为它似乎是按字母顺序排序的。我无法更改日期格式,也无法以该可排序格式添加与日期相同的第二个字段。

我还发现,如果我按原样保留日期格式,我可以按年份排序,然后按月份名称排序:

<xsl:sort select="concat(
        substring(fields/field_start_date,string-length(fields/field_start_date)-3,4),
        substring(fields/field_start_date,string-length(fields/field_start_date)-10,3),
        substring(fields/field_start_date,string-length(fields/field_start_date)-6,2)
                         )" order="ascending" />

但这不会产生所需的升序日期输出顺序,因为二月按字母顺序排在一月之前,等等。

我知道从日期末尾向后计数字符以查找每个数据组件(年、日和月)的开始看起来很奇怪,但我尝试从零和 1 向前计数,但无法做到工作。似乎月份名称从字符位置 9 开始(idk 为什么 - 关于 start_date 是一个带有字符串 + 时区 + 我期望的其他信息的复合字段)但是日期编号不像你所期望的那样从位置 13 开始我放弃了尝试通过反复试验来找到它。

鉴于上述情况,尽管我仍然需要弄清楚如何将月份名称缩写映射到数字(Jan->01、Feb->02 等),并且我找到了各种方法示例,例如@DimitreNovaatchev 的https://stackoverflow.com/a/555536/1745001,但经过一天的研究和反复试验,我无法弄清楚如何重新排列该代码或任何其他类似代码以适应我现有的 XSL 文件并在我的情况下工作。

谁能帮我解决这个问题?


上下文:

如果您访问了我的网站 http://tournamart.com/,请向下滚动到地图下方,然后在给定字段中输入这些值:

Distance From: [Oswego, Illinois, USA]  [(Drop Down:) 100 miles]
Start Date
    From: [10/01/2015]
    To:   [03/01/2015]

然后单击绿色的“开始搜索”按钮,该网站将打印 2015 年 10 月 1 日至 2016 年 3 月 1 日期间奥斯威戈 100 英里范围内即将举行的 9 场锦标赛的列表。我试图让输出按日期排序,以便最早的比赛排在第一位。在不修改代码的情况下,据我所知,输出是按照在数据库中输入的顺序排列的。

鉴于以下建议的解决方案 (https://stackoverflow.com/a/32904143/1745001):

<xsl:sort select="substring(fields/field_start_date, 8 , 4)" data-type="number" />
<xsl:sort select="string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', substring(fields/field_start_date, 1 , 3)))" data-type="number" />
<xsl:sort select="substring(fields/field_start_date, 5 , 2)" data-type="number" />

输出仍未按日期排序:

PUMA 2016 PRESIDENTS DAY INDOOR CUP
City: Sturtevant
State: Wisconsin
Start Date: Feb 13 2016

PUMA 2016 MARTIN LUTHER KING INDOOR CUP
City: Sturtevant
State: Wisconsin
Start Date: Jan 15 2016

Winter Freeze
City: Crown Point
State: Indiana
Start Date: Dec 04 2015

2015 Eclipse Select AT&T Oktoberfest Shootout
City: Waukegan
State: Illinois
Start Date: Oct 10 2015

Racine Lighthouse Classic - 2015
City: Franksville
State: Wisconsin
Start Date: Oct 10 2015

Sockers Nike Classic Cup Fall 2015
City: Chicago
State: Illinois
Start Date: Oct 09 2015

2015 Octoberfest Classic Presented by Quaker Oats
City: Libertyville
State: Illinois
Start Date: Oct 09 2015

WSA Columbus Day Classic
City: Wheeling
State: Illinois
Start Date: Oct 09 2015

Glen Ellyn Lakers FC 2015 Fall Classic
City: Glen Ellyn
State: Illinois
Start Date: Oct 02 2015

但是当我修改代码以从日期字符串的末尾开始计算字符时:

<xsl:sort select="substring(fields/field_start_date, string-length(fields/field_start_date)-3 , 4)" data-type="number" />
<xsl:sort select="string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', substring(fields/field_start_date, string-length(fields/field_start_date)-10 , 3)))" data-type="number" />
<xsl:sort select="substring(fields/field_start_date, string-length(fields/field_start_date)-6 , 2)" data-type="number" />

它似乎成功了,因为它现在生成了:

Glen Ellyn Lakers FC 2015 Fall Classic
City: Glen Ellyn
State: Illinois
Start Date: Oct 02 2015

Sockers Nike Classic Cup Fall 2015
City: Chicago
State: Illinois
Start Date: Oct 09 2015

2015 Octoberfest Classic Presented by Quaker Oats
City: Libertyville
State: Illinois
Start Date: Oct 09 2015

WSA Columbus Day Classic
City: Wheeling
State: Illinois
Start Date: Oct 09 2015

2015 Eclipse Select AT&T Oktoberfest Shootout
City: Waukegan
State: Illinois
Start Date: Oct 10 2015

Racine Lighthouse Classic - 2015
City: Franksville
State: Wisconsin
Start Date: Oct 10 2015

Winter Freeze
City: Crown Point
State: Indiana
Start Date: Dec 04 2015

PUMA 2016 MARTIN LUTHER KING INDOOR CUP
City: Sturtevant
State: Wisconsin
Start Date: Jan 15 2016

PUMA 2016 PRESIDENTS DAY INDOOR CUP
City: Sturtevant
State: Wisconsin
Start Date: Feb 13 2016

所以,这非常有帮助,谢谢,剩下的问题是:

  1. 为什么我必须从末尾倒数 char 位置?
  2. 是否有更有效(或稳健或“更好”)的方法来做到这一点?

【问题讨论】:

  • 这是 XSLT 1.0 还是 2.0? XSLT 2.0 在这方面要好得多,但是很多开源产品都停留在 XSLT 1.0 上。
  • 我不知道,但上面代码的第一行写着version="1.0",这是否意味着它是 XSLT 1.0?
  • 重要的是处理器能做什么,而不是样式表说什么。在这里查看如何找到:stackoverflow.com/questions/25244370/…
  • 好的,我查看了该参考资料并看到了一行代码。我是否将其添加到我正在编辑的文件中的某个位置?如果是在哪里?如果不是,我该怎么办?完成后我应该期待看到什么?同样,我在这个领域或使用 XLS 方面的经验绝对为零。
  • 使用这个样式表代替你的:pastebin.com/gGChraNG

标签: xslt


【解决方案1】:

我仍然需要弄清楚如何将月份名称缩写映射到 数字(Jan->01、Feb->02 等)

你可以这样做:

string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', substring($f, 1 , 3)))

这会将缩写映射为 Jan->0、Feb->3、Mar->6 等,这对于 numerical 排序来说已经足够了。

我建议您简单地使用三个数字排序指令,而不是尝试制造单个文本字符串:

<xsl:sort select="substring(fields/field_start_date, 8 , 4)" data-type="number" />
<xsl:sort select="string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', substring(fields/field_start_date, 1 , 3)))" data-type="number" />
<xsl:sort select="substring(fields/field_start_date, 5 , 2)" data-type="number" />

我知道从末尾开始计算字符看起来很奇怪 查找每个数据组件(年、日和月)的开始日期 但我尝试从零和 1 向前计数,但无法使 它工作。

如果它仍然不适合您,请发布失败的输入示例。

【讨论】:

  • 啊,要是我能弄清楚输入的来源和外观就好了。在我网站的某个地方有一个 SobiPro 数据库,我所知道的是,在那里和这里之间会发生魔法并产生输出。如果有用的话,SobIPro 字段的导出如下所示:"{""string"":""Sep 05 2015"",""timezone"":{""offset"":-18000,""timezone"":""America\/Chicago""},""timestamp"":""1441429200""}"。我会尝试您的解决方案并回复您。谢谢。
  • @EdMorton 您可以通过(仅)应用 identity transform 模板来查看原始 XML 输入的样子:en.wikipedia.org/wiki/Identity_transform#Using_XSLT --- BTW,在大多数情况下,数据库的输出已经按数据库排序,这(同样,在大多数情况下)可以更有效地完成。
  • 对不起,我确信这对其他人来说是非常基本且显而易见的,但我不能强调我对这个领域知之甚少,所以 - “应用识别转换模板”?我是否在我正在处理的文件中的某处添加来自该引用的代码 sn-ps 之一?我要添加不同的文件吗?如果是,在哪里?我做点别的吗?如果我从字符串 bt 的末尾倒数,您的解决方案确实有效,因此非常感谢您。我已经更新了我的问题,以显示当我使用您的代码和修改后的代码时会发生什么。
  • 只需按原样使用链接中显示的样式表(替换所有您的代码)。结果将是您的输入 XML 的副本。然后你就会确切地知道你在处理什么,而不是像现在这样盲目地摸索。
  • 当我这样做时,我的网站只显示The page isn't redirecting properly
猜你喜欢
  • 1970-01-01
  • 2021-01-15
  • 2012-03-17
  • 1970-01-01
  • 2022-06-14
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 2021-12-12
相关资源
最近更新 更多