XQuery:如何使用日期并比较它们

时间:2014-07-23 07:43:42

标签: xml date xquery

我有一种由这种形式的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 ...谢谢

1 个答案:

答案 0 :(得分:3)

您没有说明您是否需要XQuery 1.0解决方案,或者可以使用XQuery 3.0。

XQuery 1.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

使用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