我有一种由这种形式的file.xml构成的数据库:
<bursar>
<invoice>
<number>...</number>
<date>21/6/2014</date>
<object>...</object>
<receiver>...</receiver>
<operator>...</operatore>
</invoice>
<many other invoices>
</bursar>
我应该使用XQuery来获取两个日期之间的发票:&#34;来自&#34;约会到&#34;到&#34;日期。我如何用XQuery表达这个?我该如何比较日期?因为我猜它们作为字符串保存在file.xml中所以我不知道如何表达&#34;开始日期&#34;和&#34;结束日期&#34; ... 这就是我想要做的事情
for $v in doc('invoices.xml')//bursar/invoice
where $v/date >= "begin date" and $v/date <= "end date"
return $v
如何将这些字符串转换为实际日期以便进行比较?它们的形式为dd / mm / yyyy ...谢谢
答案 0 :(得分:3)
您没有说明您是否需要XQuery 1.0解决方案,或者可以使用XQuery 3.0。
XQuery 1.0缺少相当多的格式化功能,这将使这更容易。 FunctX function library提供了相当多的内容,所以让我们利用它们而不是编写新代码。最后,归结为分解日期并使用FunctX function functx:date(...)
(及其依赖项)来组成日期:
declare namespace functx = "http://www.functx.com";
declare function functx:date
( $year as xs:anyAtomicType ,
$month as xs:anyAtomicType ,
$day as xs:anyAtomicType ) as xs:date {
xs:date(
concat(
functx:pad-integer-to-length(xs:integer($year),4),'-',
functx:pad-integer-to-length(xs:integer($month),2),'-',
functx:pad-integer-to-length(xs:integer($day),2)))
} ;
declare function functx:pad-integer-to-length
( $integerToPad as xs:anyAtomicType? ,
$length as xs:integer ) as xs:string {
if ($length < string-length(string($integerToPad)))
then error(xs:QName('functx:Integer_Longer_Than_Length'))
else concat
(functx:repeat-string(
'0',$length - string-length(string($integerToPad))),
string($integerToPad))
} ;
declare function functx:repeat-string
( $stringToRepeat as xs:string? ,
$count as xs:integer ) as xs:string {
string-join((for $i in 1 to $count return $stringToRepeat),
'')
} ;
let $date := tokenize("21/6/2014", "/")
return functx:date($date[3], $date[2], $date[1])
绝对有可能用较少的代码编写代码,但它已经存在繁琐的重写函数。
使用XQuery 3.0,您可以使用很少的内置语句执行所有分解,格式化和日期构建:
string-join(
reverse(tokenize("21/6/2014", "/")) ! format-number(. cast as xs:integer, "00"),
'-'
) cast as xs:date
简而言之,这会对各个组件进行标记,反转它们的顺序,将其格式化为每个组件至少有两位数(需要转换为xs:date
),然后将它们重新组合为预期的模式{{1}最后投射到YYYY-MM-DD
。