Как я могу удалить дублирующиеся узлы в XQuery?

Это немного уродливо, потому что у него есть дублирование кода, но он делает трюк:

select .... where id = 5 
union
select .... where not id = 5
16
задан brabster 12 September 2009 в 19:52
поделиться

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 в все-заголовки .

16
ответ дан 30 November 2019 в 21:20
поделиться

Я решил свою проблему путем реализации рекурсивной функции поиска уникальности, базирующейся только на текстовом содержании моего документа для соответствия уникальности.

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>

я предполагаю, нужно ли Вам немного отличающееся соответствие эквивалентности, можно изменить соответствие в алгоритме соответственно. Должны запустить Вас во всяком случае.

1
ответ дан 30 November 2019 в 21:20
поделиться

Вы можете использовать встроенную функцию unique-values ​​() ...

5
ответ дан 30 November 2019 в 21:20
поделиться

А как насчет fn:distinct-values?

1
ответ дан 30 November 2019 в 21:20
поделиться

Решение, вдохновленное функциональным программированием. Это решение является расширяемым, так как вы можете заменить сравнение "=" своей настраиваемой логической 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)
2
ответ дан 30 November 2019 в 21:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: