从使用pos的this question about navigating collections开始
在eXist 4.7中,我在myapp/data/中有一个集合,其中包含数以千计的TEI XML文档。我使用Martin Honnen的以下解决方案来获取某个文档之前和之后的文档
let $data := myapp/data
let $examples := $data/tei:TEI[@type="example"]
for $example at $pos in $examples
where $example/@xml:id = 'TC0005'
return (
$examples[$pos - 1],
$example
$examples[$pos + 1]
)这样,我原本期望$examples[$pos - 1]生成文档'TC0004‘,而$examples[$pos + 1]生成'TC0006’(例如,基于eXide集合导航视图中的排序顺序)。它们不是这样做的,而是产生相反的结果。
Honnen和Michael Kay回应说
ordering of documents within a collection is very much processor-dependent应用order by $example/@xml:id ascending子句不会使结果变得更好。
因此,问题是如何在$data上强制使用字母数字顺序
非常感谢。
发布于 2019-08-19 16:49:45
似乎在XQuery级别,您可以将let $examples := $data/tei:TEI[@type="example"]更改为
let $examples := sort($data/tei:TEI[@type="example"], (), function($e) { $e/@xml:id })(假设XQuery/XPath3.1高阶sort函数可用)或
let $examples := for $e in $data/tei:TEI[@type="example"] order by $e/@xml:id return $e使用order by子句。
我不知道exist-db是否可以在创建或选择集合的过程中强制执行顺序。
发布于 2019-08-20 08:55:35
根据使用旧版本eXist的经验,在执行循环时,$pos值不是排序的位置顺序。这是通过时的位置。
您首先要做的是创建一个有序列表,然后从列表中获取您要查找的三个项目。
let $data := myapp/data[tei:TEI/@type eq 'example']
let $examples := for $e in $data order by $e/@xml:id ascending return $e
let $pos := index-of($examples/@xml:id, 'TC0005')
return if (count($pos) eq 1) then (
if ($pos gt 1) then $examples[$pos - 1] else (),
$examples[$pos]
$examples[$pos + 1]
) else ()这种方法的一个潜在问题是,您每次都必须对所有项目进行排序。创建一个经过排序的缓存列表可以缓解这个问题,还可以实现更高效的查询,您可以在查询结果中使用preceding-sibling和following-sibling。
如果if的命名约定是一致的,另一个可能的解决方案是查询之前和之后的if。
检查$pos中是否有一项是为了防止出现@xml:id不唯一的情况(是的,这会违反规范,但在现实世界的数据中会发生这种情况)或不存在任何项。请记住,index-of返回一个索引数组-0或更多。
https://stackoverflow.com/questions/57552649
复制相似问题