XQuery:"order by" 在 "for-each-pair" 中不起作用

XQuery: "order by" doesn't work in "for-each-pair"

我有 collection 1 个 xml 个文件。 collection中典型的xml文件如下:

典型的 XML 个文件来自 Collection 1

<book xml:id="1">
    <body>
        <collection>Name of collection 1</collection>
        <title>Title of book</title>
        <author>Author of book</author>
        <date>Date of publication of book</date>
        <text>This is a text of book .....</text>
    </body>
</book>

我这样查询这些文件(我必须使用XQuery而不能在这里使用XSL,这超出了我的意愿。我的整个查询要复杂得多,这里我使用一个简单的版本来显示,充其量我的代码和我的问题):

来自 Collection 的 XML 个文件的 XQuery 1

for $book in collection("path_to_collection_1")
    let $collection_name := data($book/collection)
    let $title := data($book/title)
    let $author := data($book/author)
    let $date := data($book/date)

    where $date >= '2000'
    order by $date
return
<book>
    <collection_name>{$collection_name}</collection_name>
    <title>{$title}</title>
    <author>{$author}</author>
    <date>{$date}</date>
</book>

来自 Collection 1 XML 个文件的 XQuery 结果 (关注date)

1
<book>
    <collection_name>Collection 1</collection_name>
    <title>This is a best novel in the word</title>
    <author>Lebowski, Big</author>
    <date>2001</date>
</book>

2
<book>
    <collection_name>Collection 1</collection_name>
    <title>Another greate book</title>
    <author>Lincoln, Abraham</author>
    <date>2005</date>
</book>

3
<book>
    <collection_name>Collection 1</collection_name>
    <title>The story of my life</title>
    <author>Mouse, Mickey</author>
    <date>2012</date>
</book>
    etc. etc. etc.

好的,效果不错。

还有,我有一个collection 2。第二个collection中的XML个文件和collection 1中的文件基本一样,只是在结构上或一些节点的名字上有一些小的区别,所以我不得不使用不同的查询。

典型的 XML 个文件来自 Collection 2

<collection>
    <this_is_book>
        <data_about_book>
            <name_of_collection>Name of collection 2</name_of_collection>
            <title>Title of book</title>
            <author>Author of book</author>
            <date_of_publication>Date of publication of book</date_of_publication>
        </data_about_book>
        <text_of_book>
            <text>This is a text of book.....</text>
        </text_of_book>
    </this_is_book>
</collection>

来自 Collection 的 XML 个文件的 XQuery 2

for $book in collection("path_to_collection_2")
    let $collection_name := data($book//name_of_collection)
    let $title := data($book//title)
    let $author := data($book//author)
    let $date := data($book//date_of_publication)

    where $date >= '2000'
    order by $date
return
<book>
    <collection_name>{$collection_name}</collection_name>
    <title>{$title}</title>
    <author>{$author}</author>
    <date>{$date}</date>
</book>

来自 Collection 2 XML 个文件的 XQuery 结果 (关注date)

1
<book>
    <collection_name>Collection 2</collection_name>
    <title>Why I crossed the Rubicon river</title>
    <author>Caesar, Julius</author>
    <date>2003</date>
</book>

2
<book>
    <collection_name>Collection 2</collection_name>
    <title>Colonize it!</title>
    <author>Musk, Elon</author>
    <date>2007</date>
</book>

3
<book>
    <collection_name>Collection 2</collection_name>
    <title>I have no more imagination</title>
    <author>Lennon, John</author>
    <date>2011</date>
</book>
    etc. etc. etc.

好的,效果不错。

我的第一个问题是合并两个查询的结果(我必须能够在同一个 XQuery 中查询两个 collection)。为此,我使用函数 for-each-pair(这是我的另一个问题 的主题,非常感谢 Martin Honnen 的回答和建议)。

所以,我当前代码的简单架构如下:

for-each-pair(
  collection("path_to_collection_1"),
  collection("path_to_collection_2"),
  function($collection1, $collection2) {
    for $book in $collection1
        ... etc. (see above the whole query for 'collection 1')
    ,
    for $book in $collection2
        ... etc. (see above the whole query for 'collection 2')
  }
)

我目前的成绩 (关注date)

1
<book>
    <collection_name>Collection 1</collection_name>
    <title>Another greate book</title>
    <author>Lincoln, Abraham</author>
    <date>2005</date>
</book>

2
<book>
    <collection_name>Collection 1</collection_name>
    <title>This is a best novel in the word</title>
    <author>Lebowski, Big</author>
    <date>2001</date>
</book>

3
<book>
    <collection_name>Collection 1</collection_name>
    <title>The story of my life</title>
    <author>Mouse, Mickey</author>
    <date>2012</date>
</book>

4
<book>
    <collection_name>Collection 2</collection_name>
    <title>Colonize it!</title>
    <author>Musk, Elon</author>
    <date>2007</date>
</book>

5
<book>
    <collection_name>Collection 2</collection_name>
    <title>Why I crossed the Rubicon river</title>
    <author>Caesar, Julius</author>
    <date>2003</date>
</book>

6
<book>
    <collection_name>Collection 2</collection_name>
    <title>I have no more imagination</title>
    <author>Lennon, John</author>
    <date>2011</date>
</book>
    etc. etc. etc.

所以第二个查询的结果附加到第一个查询的结果。但是有一个问题:order by $date 子句不再起作用了...

我的问题和期望的结果:

  1. 至少。如何在每个结果中应用order by子句?至少,我想要 result from collection 1 ordered by date + result from collection 2 ordered by date.

  2. 充其量。 是否可以将 order by 子句应用于整个结果(即来自 collections 1 的组合结果和2)?充其量,我想要 result from collection 1 + result from collection 2 and then order all this by date)?或者,为此,我必须完全改变我的方法并使用 for-each-pair 函数以外的其他东西?在这种情况下,哪个?

期望(最多)结果的示例。 (注意datecollection_name

1
<book>
    <collection_name>Collection 1</collection_name>
    <title>This is a best novel in the word</title>
    <author>Lebowski, Big</author>
    <date>2001</date>
</book>

2
<book>
    <collection_name>Collection 2</collection_name>
    <title>Why I crossed the Rubicon river</title>
    <author>Caesar, Julius</author>
    <date>2003</date>
</book>

3
<book>
    <collection_name>Collection 1</collection_name>
    <title>Another greate book</title>
    <author>Lincoln, Abraham</author>
    <date>2005</date>
</book>

4
<book>
    <collection_name>Collection 2</collection_name>
    <title>Colonize it!</title>
    <author>Musk, Elon</author>
    <date>2007</date>
</book>

5
<book>
    <collection_name>Collection 2</collection_name>
    <title>I have no more imagination</title>
    <author>Lennon, John</author>
    <date>2011</date>
</book>

6
<book>
    <collection_name>Collection 1</collection_name>
    <title>The story of my life</title>
    <author>Mouse, Mickey</author>
    <date>2012</date>
</book>
    etc. etc. etc.

非常感谢您的帮助!

编辑 1: 我以 order by date 为例。在实际代码中,我必须能够按 order by titleorder by author 等不同元素(由用户选择)进行排序(但我不需要应用许多不同的 orders by同时。)所以,也许解决方案应该更“通用”,而不是特别依赖于 order by date?

当每个项目遍历两个序列时,该函数将应用于每个项目。我认为您需要对 for-each-pair() 的前两个参数中发送的项目集合进行排序,而不是尝试执行一种排序,当它应用第三个参数的函数时,每个项目将是一个项目。

例如,使用一个函数,在该函数中您提供馆藏的名称来获取过滤后的书籍集,并按日期对两个馆藏进行排序作为前两个参数,然后第三个参数的函数简单地将项目和 returns 作为一个序列:

declare function local:sortByDate($path_to_collection) {
  for $book in collection($path_to_collection)
  let $collection_name := data($book//name_of_collection)
  let $title := data($book//title)
  let $author := data($book//author)
  let $date := data($book//date_of_publication)
  where $date >= '2000'
  order by $date
  return $book
};

for-each-pair(
  local:sortByDate("path_to_collection_1"),
  local:sortByDate("path_to_collection_2"),
  function($collection1, $collection2) {
    $collection1, $collection2
  }
)

其实很简单。只需要将 for-each-pair 的组合结果作为序列放入变量中。然后循环遍历此序列的所有项目并根据需要对它们进行排序。瞧!

这种方法的简单架构:

let $results_not_sorted := (
    for-each-pair (
      collection("path_to_collection_1"),
      collection("path_to_collection_2"),
      function($collection1, $collection2) {
        for $book in $collection1
            ... etc. (see above the whole query for 'collection 1')
        ,
        for $book in $collection2
            ... etc. (see above the whole query for 'collection 2')
      }
    )
) 
for $result in $results_not_sorted
    order by $result//date (:sort here by whatever you want)
return
    $result

详细代码:

let $results_not_sorted := (
    for-each-pair (
      collection("path_to_collection_1"),
      collection("path_to_collection_2"),
      function($collection1, $collection2) {
        for $book in $collection1
            let $collection_name := data($book/collection)
            let $title := data($book/title)
            let $author := data($book/author)
            let $date := data($book/date)
            where $date >= '2000'
        return
            <book>
                <collection_name>{$collection_name}</collection_name>
                <title>{$title}</title>
                <author>{$author}</author>
                <date>{$date}</date>
            </book>
        ,
        for $book in $collection2
            let $collection_name := data($book//name_of_collection)
            let $title := data($book//title)
            let $author := data($book//author)
            let $date := data($book//date_of_publication)
            where $date >= '2000'
        return
            <book>
                <collection_name>{$collection_name}</collection_name>
                <title>{$title}</title>
                <author>{$author}</author>
                <date>{$date}</date>
            </book>
      }
    )
) 
for $result in $results_not_sorted
    order by $result//date (:sort here by whatever you want)
return
    $result