【问题标题】:XQuery : how to get distinct values of substrings?XQuery:如何获得子字符串的不同值?
【发布时间】:2012-12-18 03:11:15
【问题描述】:

我的 XML 文件是这样的:

<element id="1" time="05-08-2012T12:00">...</element>
<element id="2" time="05-08-2012T13:00">...</element>
<element id="3" time="05-08-2012T14:00">...</element>
...
<element id="13" time="06-08-2012T00:00">...</element>
<element id="14" time="06-08-2012T01:00">...</element>

现在我想做的是:

  • 创建一个仅包含不同日期的 HTML 选项框。我试过这个:

for $d in //mesure/@date

for $date in substring($d,0,11)

返回不同的值($date)

但它一直返回“05-08-2012”的次数与在 XML 文件中打印的次数一样多。

  • 我还想知道如何更改我在 HTML 选项框中输入的值(例如,“05-08-2012”将变为“2012 年 8 月 5 日”)。应该使用函数吗?

  • 最后,我想保留包含给定日期的第一个元素的 id,这样当我在 HTML 选择框中选择它时,我可以使用该日期的所有元素。

【问题讨论】:

    标签: xml xquery


    【解决方案1】:

    使用

    distinct-values(//measure/@date/substring-before(.,'T'))
    

    要获得完整的所需结果,请使用

      let $months := ('January', 'February', 'March', 'April', 'May', 'June', 'July',
                      'August', 'September', 'October', 'November', 'December'),
        $dates := distinct-values(//measure/@date/substring-before(.,'T'))
     return
        for $date in $dates,
            $d in tokenize($date, '-')[1],
            $m in xs:integer(tokenize($date, '-')[2]),
            $y in tokenize($date, '-')[3]
         return
            ($d, $months[$m], $y, '&#xA;')
    

    将此 XQuery 应用于以下 XML 文档的结果

    <t>
        <measure id="1" date="05-08-2012T12:00">...</measure>
        <measure id="2" date="05-08-2012T13:00">...</measure>
        <measure id="3" date="05-08-2012T14:00">...</measure>
    ...
        <measure id="13" date="06-08-2012T00:00">...</measure>
        <measure id="14" date="06-08-2012T01:00">...</measure>
    </t>
    

     05 August 2012 
     06 August 2012 
    

    【讨论】:

    • 既然已经有了更好的抽象内置函数:format-date、format-dateTime 等,为什么还要重新发明轮子?
    • @wst,不,没有。不在建议书中。这些是 XPath.30 函数,不适用于标记为“xquery”但不适用于“xquery-3.0”或“xpath-3.0”的问题。在否决除您之外的所有其他答案之前,最好先看看您自己的答案,该答案提供了不存在(作为标准)功能的不完整提示。我应该提到三个答案中的哪一个最值得被否决吗?
    • 您应该提及还是已经提及?你的模棱两可使它不清楚。此外,OP 没有指定 XQuery 版本或处理器。
    【解决方案2】:

    这是因为如果你对 $date 应用 distinct-values,$date 只有一个值(并且一个值总是不同的)。您需要将其应用于整个序列,即

     distinct-values( for $d in //mesure/@date return  substring($d,0,11) )
    

    要更改日期,最好使用 tokenize 函数拆分组件,然后重新排序。

    let $splitDate := tokenize("05-08-2012", "-"), $monthNames := ("January", "February" , ...) 
    return concat($splitDate[1] cast as integer, " ", $monthNames[$splitDate[2] cast as integer], " ", $splitDate[3])
    

    您可以尝试 xs:date(..) 将日期读取为真实日期,然后使用 XQuery 日期函数打印它,但是您输入的日期的组件顺序错误,因此 XQuery 可能无法解析它...

    【讨论】:

    • @wst:规范在哪里有日期解析功能?他们无处可寻。 (xs:date("06-08-2012")` 不起作用。)
    • @wst:但是在哪里?在发布我的答案之前,我实际上已经看过了,但找不到任何答案。
    • @wst:但那是日期格式化解析的日期在哪里?没有解析就没有什么可以格式化...
    • @wst:好吧,如果你不得不使用 replace,你也可以使用 tokenize...
    • @wst,如果您称其为“非常简单的正则表达式”...,则标记化应该是“超级简单的”:) 在 3 个小时里,您一直在告诉我们一些所谓的“日期解析” " WD 中的函数,直到你发现没有这样的......
    【解决方案3】:

    您需要获取序列上的不同值:

    distinct-values(//mesure/@date/substring(.,0,11))
    

    可以在 xs:dateTime 值上使用 fn:format-dateTime 格式化日期:

    format-dateTime($d, "[D] [MNn] [Y]")
    => 5 August 2012
    

    对于您的最后一个问题,您需要更具体地说明您希望对这些元素的 ID 做什么,并提供有关此数据的更多信息。 (这应该是一个单独的问题)

    【讨论】:

    • 提供使用仅在 XQuery 3.0 (F & O 3.0) 中可用的功能,这仍然不是 w3C 推荐 - 不是一个好建议。由于 OP 没有将其标记为“xslt-3.0”或“xpath-3.0”,他可能对(或不能使用)XQuery 3.0 不感兴趣。您既没有为此提供好的建议,也没有为问题提供完整的解决方案。
    • 更不用说提供的 XPath 3.0 函数只接受 xs:date 作为其第一个参数,而没有任何不同的值。
    • 非常感谢您的回答,但我只使用 XQuery 1/2,所以我不能使用 format-dateTime。但我会牢记这个想法。
    • @DimitreNovaatchev format-dateTime 接受 xs:dateTime。 xs:date 和 xs:dateTime 有 2 个互补函数。
    • @wst,问题中的值都不是这些。
    猜你喜欢
    • 2021-05-31
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多