我的问题似乎微不足道,但无法弄清楚如何解析包含逗号分隔的日期列表的字符串。各个日期的解析部分不是问题,但空值是。麻烦的是日期的顺序很重要,有些日期可以省略。预计日期格式为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的空文字可以很好地解决问题,但是唉。
答案 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)
除上述之外的多个选项..
返回一系列函数,在调用时返回日期
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) ;
返回标记化且经过验证但未解析的字符串。使用""因为'无效',例如:
( "2014-01-22","","2017-03-30","" )
然后是数组',地图,地图数组和...... XML parseFunction()as xs:element()*:
for ... return <date>{ parse-and-validate($value) } </date>