Reputation: 841
My xml file complies to the following DTD:
<!ELEMENT eprints (paper+)>
<!ELEMENT paper (eprintsid,userid,dir,datestamp,type,author+,title)>
<!ELEMENT eprintsid (#PCDATA)>
<!ELEMENT userid (#PCDATA)>
<!ELEMENT dir (#PCDATA)>
<!ELEMENT datestamp (#PCDATA)>
<!ELEMENT type (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ATTLIST author id CDATA #REQUIRED>
From this xml file I want to generate a list nodes of all distinct-values text nodes of author that match multiple id value, with the multiple id's as childnodes.
Therefore I tried using the following xquery:
let $doc := doc("eprints")
for $i in distinct-values($doc//author)
let $jn := $i/@id
where (count(distinct-values($jn)) > 1)
return <idByAuthor>{$jn}</idByAuthor>
Apparently XQuery does not allow me to traverse to the 'id' attribute node of $i
, as I get the following error (from my xml database engine BaseX):
'context node required for '@id'; xs:untypedAtomic found.'.
Does anyone know why I can't reach the id attribute of $i
?
Upvotes: 2
Views: 2013
Reputation: 1577
you might want to have a look at the group by
expression, introduced with XQuery 3.0 (see BaseX Doc).
Group by allows you to perform value based grouping, as such you could do something like in this Gist, Group By Example:
let $authors :=
<authors>
<author id="a"><name>Foo</name>…whatever…</author>
<author id="b"><name>Foo</name>…whatever…</author>
<author id="a"><name>Foo</name>…whatever…</author>
<author id="c"><name>Bar</name>…whatever…</author>
<author id="d"><name>Bar</name>…whatever…</author>
<author id="f"><name>FooBar</name>…whatever…</author>
</authors> (: or use doc('eprints')//author :)
return
<distinct-names> {
for $author in $authors//author
group by $name := $author/name
return
if(count(distinct-values($author/@id)) > 1) then
element {"author"}
{
attribute {"name"} {$name},
for $id in distinct-values($author/@id)
return <id>{$id}</id>
}
else ()
}</distinct-names>
I hope this helps, otherwise feel free to post a small snippet of your XML file.
Kind regards Michael
Upvotes: 2
Reputation: 38732
distinct-values(...)
returns a set of atomic values (eg., numbers and strings), not XML nodes. You cannot do an axis step from these.
From this xml file I want to generate a list nodes of all distinct-values text nodes of author that match multiple id value, with the multiple id's as childnodes.
That's not the problem you want to solve, that's the way you're trying to solve it. I guess you want to query all authors which provided more than one paper (or what ever they're author of). If I guessed wrong please write exactly what your query should do.
Try following this sketch (not valid XQuery yet):
for all authors $a
where count of all papers with author $a
return <idByAuthor>{$a/@id}</idByAuthor>
If you need more help with this query, please post some example XML snippet to work with, if you've got some code for the query this code and the desired output.
Code for clearified question:
for $author in distinct-values($doc//author)
let $ids := $doc//author[data()=$author]/@id/data()
where count($ids) > 1
return
<author name="{ $author }">
{
for $id in $ids
return <id>{ $id }</id>
}
</author>
Upvotes: 4