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

时间:2017-05-31 10:49:33

标签: xquery marklogic

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

因此,以下是有效输入和预期返回值:

   ,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中似乎没有等效的返回值作为省略日期的占位符,如果你想返回一个序列,那就是。因为包含在序列中的空序列被夷为平面。

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

谢谢你,
ķ。

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

更新:感谢两个答案,最后我选择使用占位符日期,因为XQuery与序列的工作非常好,其他任何东西都需要在其他地方进行一些更改。但问题仍然存在于所需的返回值是数值的情况。在这种情况下,使用占位符值可能是不可行的。 xs:anyAtomicType的空文字可以很好地解决问题,但是唉。

2 个答案:

答案 0 :(得分:2)

您可以考虑在json:array()array-node{}内加null-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 :(得分:1)

除上述之外的多个选项..

  1. 返回一系列函数,在调用时返回日期

    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. 返回标记化且经过验证但未解析的字符串。使用""因为'无效',例如:

    ( "2014-01-22","","2017-03-30","" )
    
  3. 然后是数组',地图,地图数组和...... XML parseFunction()as xs:element()*:

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