Это немного уродливо, потому что у него есть дублирование кода, но он делает трюк:
select .... where id = 5
union
select .... where not id = 5
А более простая и более прямая острота решение XPath:
Просто используют следующее выражение XPath :
/*/book
[index-of(/*/book/title,
title
)
[1]
]
При применении, например, на следующем XML-документе :
<books>
<book>
<title>XML in 24 hours</title>
<author>Some Guy</author>
</book>
<book>
<title>Food in Seattle</title>
<author>Some Guy2</author>
</book>
<book>
<title>XML in 24 hours</title>
<author>Some Guy</author>
</book>
<book>
<title>Food in Seattle</title>
<author>Some Guy2</author>
</book>
<book>
<title>How to solve XPAth Problems</title>
<author>Me</author>
</book>
</books>
вышеупомянутое выражение XPath выбирает правильно следующие узлы :
<book>
<title>XML in 24 hours</title>
<author>Some Guy</author>
</book>
<book>
<title>Food in Seattle</title>
<author>Some Guy2</author>
</book>
<book>
<title>How to solve XPAth Problems</title>
<author>Me</author>
</book>
объяснение просто: Для каждого book
, выберите только одно из его происшествий - таким образом, что его индекс в все-книги совпадает с первым индексом title
в все-заголовки .
Я решил свою проблему путем реализации рекурсивной функции поиска уникальности, базирующейся только на текстовом содержании моего документа для соответствия уникальности.
declare function ssd:unique-elements($list, $rules, $unique) {
let $element := subsequence($rules, 1, 1)
let $return :=
if ($element) then
if (index-of($list, $element) >= 1) then
ssd:unique-elements(insert-before($element, 1, $list), subsequence($rules, 2), $unique)
else <test>
<unique>{$element}</unique>
{ssd:unique-elements(insert-before($element, 1, $list), subsequence($rules, 2), insert-before($element, 1, $unique))/*}
</test>
else ()
return $return
};
Названный следующим образом:
declare function ssd:start2() {
let $data := ()
let $sift-this :=
<test>
<data>123</data>
<data>456</data>
<data>123</data>
<data>456</data>
<more-data>456</more-data>
</test>
return ssd:unique-elements($data, $sift-this/*, ())/*/*
};
ssd:start2()
вывод:
<?xml version="1.0" encoding="UTF-8"?>
<data>123</data>
<data>456</data>
я предполагаю, нужно ли Вам немного отличающееся соответствие эквивалентности, можно изменить соответствие в алгоритме соответственно. Должны запустить Вас во всяком случае.
Вы можете использовать встроенную функцию unique-values ()
...
Решение, вдохновленное функциональным программированием. Это решение является расширяемым, так как вы можете заменить сравнение "=" своей настраиваемой логической local: compare ($ element1, $ element2)
функцией. Эта функция имеет квадратичную сложность наихудшего случая по длине списка. Вы можете получить n (log n)
сложность, отсортировав список перед и сравнивая только с непосредственным преемником.
Насколько мне известно, функции fn: independent-values
(или fn: independent-elements
) не позволяют использовать настраиваемые функция сравнения.
declare function local:deduplicate($list) {
if (fn:empty($list)) then ()
else
let $head := $list[1],
$tail := $list[position() > 1]
return
if (fn:exists($tail[ . = $head ])) then local:deduplicate($tail)
else ($head, local:deduplicate($tail))
};
let $list := (1,2,3,4,1,2,1) return local:deduplicate($list)