XQuery/时间比较与 XQuery
外观
< XQuery
你有两个包含时间戳的相同项目列表。你想比较这些项目以查看哪些项目更新。
我们将编写一个函数来比较两个列表中项目的 时间戳。
let $list1 :=
<list>
<item dateTime="2009-06-01T11:59:00.000-05:00">apples</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">carrots</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">eggplant</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">grapes</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">oranges</item>
</list>
let $list2 :=
<list>
<item dateTime="2009-01-01T11:59:00.000-05:00">apples</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
<item dateTime="2009-03-01T11:59:00.000-05:00">carrots</item>
<item dateTime="2009-02-01T11:58:00.000-05:00">eggplant</item>
<item dateTime="2009-02-01T12:00:00.000-05:00">grapes</item>
<item dateTime="2009-04-01T11:59:00.000-05:00">oranges</item>
</list>
declare function local:older($list1 as node()*, $list2 as node()*) as node()* {
for $item1 in $list1/item
let $item2 := $list2/item[./text() = $item1/text()]
return
<div>
{attribute {'class'}
{if ( xs:dateTime($item1/@dateTime) lt xs:dateTime(fn:current-dateTime) )
then 'older'
else 'newer'
}
}
{$item1/text()}
</div>
};
<html>
<head>
<style language="text/css">
<![CDATA[
body {font-family: Ariel,Helvetica,sans-serif; font-size: medium;}
h2 {padding: 3px; margin: 0px; text-align: center; font-size: large; background-color: silver;}
.left, .right {border: solid black 1px; padding: 5px;}
.older {background-color: pink;}
.left {float: left; width: 390px}
.right {margin-left: 410px; width: 390px}
]]>
</style>
</head>
<body>
<h1>Older Items on Second List Report</h1>
<div class="left">
<h2>List 1</h2>
{for $item in $list1/item return <div>{$item/@dateTime} dateTime={string(fn:current-dateTime)}</div>}
</div>
<div class="right">
<h2>List 2</h2>
{for $item in $list2/item return <div>{$item/text()} dateTime={string($item/@dateTime)}</div>}
</div>
<br/>
<p>The pink items are older items.</p>
<div class="left">
<h2>Items on 2 Older Then 1</h2>
{local:older($list1, $list2)}
</div>
<div class="right">
<h2>Items on 1 Older Then 2</h2>
{local:older($list2, $list1)}
</div>
</body>
</html>
或者,两个排序列表可以整理起来以推导出更新集。这里将项目包装在 div 中以携带关于合并的附加信息。列表 1 中但不在列表 2 中的项目标记为新建,列表 2 中但不在列表 1 中的项目标记为要删除,列表 1 中比列表 2 更新的项目标记为更新。
declare function local:merge($a, $b as node()*) as node()* {
if (empty($a) and empty($b))
then ()
else if (empty ($b) or $a[1] lt $b[1])
then (<div class="add">{$a[1]}</div>, local:merge(subsequence($a, 2), $b))
else if (empty($a) or $a[1] gt $b[1])
then (<div class="delete">{$b[1]}</div>,local:merge($a, subsequence($b,2)))
else (<div class="{ if (xs:dateTime($a[1]/@dateTime) gt xs:dateTime($b[1]/@dateTime))
then "newer"
else "older"}">
{$a[1]}
</div>,
local:merge(subsequence($a,2), subsequence($b,2))
)
};
样本数据和主脚本稍作更改
declare option exist:serialize "method=xhtml media-type=text/html";
let $list1 :=
<list>
<item dateTime="2009-06-01T11:59:00.000-05:00">apples</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">carrots</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">cabbage</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">eggplant</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">grapes</item>
</list>
let $list2 :=
<list>
<item dateTime="2009-01-01T11:59:00.000-05:00">apples</item>
<item dateTime="2009-02-01T11:59:00.000-05:00">bananas</item>
<item dateTime="2009-03-01T11:59:00.000-05:00">carrots</item>
<item dateTime="2009-02-01T11:58:00.000-05:00">eggplant</item>
<item dateTime="2009-02-01T12:00:00.000-05:00">grapes</item>
<item dateTime="2009-04-01T11:59:00.000-05:00">oranges</item>
</list>
return
<html>
<head>
<style language="text/css">
<![CDATA[
body {font-family: Ariel,Helvetica,sans-serif; font-size: medium;}
h2 {padding: 3px; margin: 0px; text-align: center; font-size: large; background-color: silver;}
.left, .right {border: solid black 1px; padding: 5px;}
.newer{background-color: lightgreen;}
.older{background-color: lightred;}
.delete{background-color: red;}
.add{background-color: green;}
.left {float: left; width: 390px}
.right {margin-left: 410px; width: 390px}
]]>
</style>
</head>
<body>
<h1>Update Report</h1>
<div class="left">
<h2>List 1</h2>
{for $item in $list1/item return <div>{$item/text()} dateTime={string($item/@dateTime)}</div>}
</div>
<div class="right">
<h2>List 2</h2>
{for $item in $list2/item return <div>{fn:current-dateTime} dateTime={string(dateTime(current-dateTime))}</div>}
</div>
<br/>
<p>Green are new, light green are newer and red to be removed</p>
<div class="left">
<h2>Merged Lists</h2>
{local:merge($list1/item, $list2/item)}
</div>
</body>
</html>