0

I am having trouble creating an XQuery 3.0 (using BaseX 9.7) to retrieve names of XML files in a collection which satisfies certain conditions: Having more than 1 occurrence of the same 'type' element if another element ('author') has a certain value.

Simplified XML examples:

"good.xml":

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <!-- OK -->
    <books>
        <book>
            <author>Alice</author>
            <type>mystery</type>
        </book>
        <book>
            <author>Alice</author>
            <type>fantasy</type>
        </book>
    </books>

"not_good.xml":

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- NOT OK -->
<books>
    <book>
        <author>Alice</author>
        <type>horror</type>
    </book>
    <book>
        <author>Alice</author>
        <type>horror</type>
    </book>
</books>

If the number of possible 'type' are small, I can use the following XQuery:

for $books in collection('group_test')/books[
       count(.//book[author = 'Alice'][type = 'mystery']) > 1
    or count(.//book[author = 'Alice'][type = 'fantasy']) > 1
    or count(.//book[author = 'Alice'][type = 'horror']) > 1
]
return db:path($books)

I have tried the following XQuery, but it does not find anything:

for $books in collection('group_test')/books[/book/author = 'Alice']
group by $type := //book/type 
where count($type) > 1

return db:path($books)
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
kDjakman
  • 116
  • 5

1 Answers1

1

Perhaps

for $book in collection('group_test')/books/book[author = 'Alice']
group by $type := $book/type 
where count($book) > 1

return ($book!db:path(.))
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • This almost works for me. I just need to wrap the return value expression with distinct-values() function call to eliminate the repeating of identical values – kDjakman Jul 11 '22 at 11:52
  • Can you explain the use of the exclamation point in the return value expression? – kDjakman Jul 11 '22 at 11:54
  • The `!` is the "map" operator in XPath/XQuery 3 (`$book!db:path(.)` being equivalent to `for $node in $book return db:path($node)`), I used it as after the `group by` the variable `$book` can be bound to a sequence of `book` elements having the same type and as I think the BaseX `db:path` function only takes a single node. – Martin Honnen Jul 11 '22 at 12:50