在 XQuery 中解析日期数组(MarkLogic v8 风格)

Parsing an array of dates in XQuery (MarkLogic v8 flavour)

我的问题看似微不足道,但无法弄清楚如何解析包含以逗号分隔的日期列表的字符串。单个日期的解析部分不是问题,但空值是。问题是日期的顺序很重要,有些日期可以省略。预计日期格式为 YYYY-mm-dd

因此,以下是有效输入和预期的 return 值:

   ,2000-12-12,2012-05-03, ➔ ( NULL, 2000-12-12, 2012-05-03, NULL )
   2000-12-12,,2012-05-03  ➔ ( 2000-12-12, NULL, 2012-05-03 )

这是我的函数签名

declare function local:assert-date-array-param( 
          $input as xs:string
        , $accept-nulls as xs:boolean?
) as xs:date*

在意识到 XQuery 中似乎没有 NULL 的等价物作为省略日期的占位符的 returned 值后,我意识到了这个问题,如果你想 return 一个序列,那是。因为包裹在序列中的空序列被展平为空。

我想,我的后备方案是使用像 1900-01-01 这样的日期作为占位符或 return 地图而不是序列,但我确实希望找到更优雅的方式

谢谢,
K.

PS。我正在使用 MarkLogic v8(以及即将推出的 v9),任何解决方案都应该使用他们的 XQuery 处理器执行。

更新:感谢这两个答案,最后我选择了占位符日期,因为 XQuery 可以很好地处理序列,其他任何内容都需要在其他地方进行一些更改。但是对于所需的 return 值是数字的情况,问题仍然存在。在这种情况下,使用占位符值可能不可行。 xs:anyAtomicType 的空字面值本来可以很好地解决这个问题,但是唉。

您可以考虑返回一个 json:array(),或一个包含 null-node{}array-node{}。但也许空日期占位符并不像听起来那么糟糕:

declare variable $null-date := xs:date("0001-01-01");

declare function local:assert-date-array-param( 
  $input as xs:string,
  $accept-nulls as xs:boolean?
) as xs:date*
{
  for $d in fn:tokenize($input, "\s*,\s*")
  return
    if ($d eq "") then
      if ($accept-nulls) then
        $null-date
      else
        fn:error(xs:QName("NULL-NOT-ALLOWED"), "Date is required")
    else
      if ($d castable as xs:date) then
        xs:date($d)
      else if ($d castable as xs:dateTime) then
        xs:date(xs:dateTime($d))
      else
        fn:error(xs:QName("INVALID-DATE"), "Invalid date format: " || $d)
};

declare function local:print-date-array($dates) {
  string-join(for $d in $dates return if ($d eq $null-date) then "NULL" else fn:string($d), ", ")
};

local:print-date-array(
  local:assert-date-array-param(",2000-12-12,2012-05-03,", fn:true())
),
local:print-date-array(
  local:assert-date-array-param("2000-12-12,,2012-05-03", fn:true())
)

HTH!

多种选择.. 除了上述。

  1. return 函数序列,调用时 return 日期

    for $i in string-tokenize-to-sequence-of-strings()
    let $dt := my-parse-date($i)
    return function() { $dt ;}
    

    return function() { return my-parse-date($i)  ; 
    
  2. return 标记化并验证但未解析的字符串。使用 "" 表示 'not valid',例如:

    ( "2014-01-22","","2017-03-30","" )
    
  3. 然后是数组、地图、地图数组,以及... XML parseFunction() 作为 xs:element()*:

    for ... return <date>{ parse-and-validate($value) } </date>