TITLE: | TMQL Use Case Solutions |
SOURCE: | Mr. Robert Barta; Mr. Lars Marius Garshol |
PROJECT: | WD 18048: Information technology -- Topic Maps -- Topic Maps Query Language (TMQL) |
PROJECT EDITOR: | Mr. Robert Barta; Mr. Lars Marius Garshol |
STATUS: | Informational |
ACTION: | For review and comment |
DATE: | 2004-03-16 |
DISTRIBUTION: | SC34 and liaisons |
REFER TO: | N0449 - 2003-11-07 - Topic Map Query Language, Use Cases |
REPLY TO: |
Dr. James David Mason (ISO/IEC JTC 1/SC 34 Secretariat - Standards Council of Canada) Crane Softwrights Ltd. Box 266, Kars, ON K0A-2E0 CANADA Telephone: +1 613 489-0999 Facsimile: +1 613 489-0995 Network: jtc1sc34@scc.ca http://www.jtc1sc34.org |
This document collects solutions to the TMQL use cases in different languages into a single document for comparison purposes. The idea is that seeing how these use cases are solved in different languages will allow readers to compare the languages and get an idea of the strengths and weaknesses of each, in order to help the committee make an informed decision about how to proceed with the TMQL standard.
This document contains solutions to 29 use cases in the following languages:
Query language | Solutions |
AsTMa? | 29 |
TMPath | 27 |
Toma | 27 |
tolog | 25 |
The following solutions are samples only; in most languages there are several ways to achieve the goal of one and the same query. These solutions might therefore differ considerably in length and complexity, depending on the trade-off between conciseness or readability. Some solutions only may demonstrate language features.
It should also be noted that what this survey shows the most clearly is differences in syntax. However, syntax is easily adjusted, and what really needs to be compared are the evaluation models. Therefore one important consideration is the extent to which the syntaxes should and could be changed.
Retrieve all author names
function test (map $m) as list return ($m / is-author-of / author/bn @uc)
list { for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] return $Author/bn::*[1] }
select $author.bn@uc where is-author-of->author = $author;
select $NAME from is-author-of($AUTHOR : author, $WORK : opus), name($AUTHOR, $NAME)?
Retrieve all author names sorted
function test (map $m) as list return ($m / is-author-of / author /bn@uc) unique sort by $a/bn@sort
list{ for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] order by $Author/bn::*@sort[1] return $Author/bn::*[1] }
select $author.bn@uc where is-author-of->author = $author order by $author.bn@sort;
select $AUTHOR from is-author-of($AUTHOR : author, $WORK : opus) order by $AUTHOR?
Retrieve the titles of all tutorials. The titles should be preferably those in scope en, de or in the unconstrained scope, in that order.
function test (map $m) as list return { forall $t [ $d (tutorial) bn @ (en | de | uc): $title ] in $m return ($title) }
list{ for $Tutorial in /topic[tutorial] return ( $Tutorial/bn::*@en[1], $Tutorial/bn::*@de[1], $Tutorial/bn::*[1]) }
select $topic.bn@$scope where $topic.type(1).id = 'tutorial' and exists $topic.bn@$scope and $scope.id in ('en', 'de', 'uc');
Retrieve the names of all persons who have not authored anything
function test (map $m) as list return $m / person [ not . -> author \ is-author-of ] / bn
list{ for $Person in /topic[person;not(roleOf::author[is-author-of]/role::opus)] return $Person/bn::*[1] }
select $person.bn@uc where is-author-of->author != $person and $person.type(1).id = 'person';
select $PERSON from instance-of($PERSON, person), not(is-author-of($PERSON : author, $WORK : opus))?
Retrieve a list of all author names together with the title of their publications
function test (map $m) as list return $m / is-author-of < . / author / bn@sort , . / opus / bn >
list{ for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] for $Pub in $Author/roleOf::author[is-author-of]/role::opus return list{$Author/bn::*[1],$Pub/bn::*[1]} }
select $author.bn@uc, $opus.bn where is-author-of->author = $author and is-author-of->opus = $opus;
is-author-of($PERSON : author, $WORK : opus)?
Retrieve a list of all titles of documents which are tutorials, sorted by publication date, descending
function test (map $m) as list return $m / tutorial < ./bn, ./in(publication-date) sort by ./in(publication-date) desc >
list{ for $Pub in /topic[tutorial] order by !$Pub/oc::publication-date descending return list{!$Pub/bn::*,!$Pub/oc::publication-date} }
select $tutorial.bn where $tutorial.type(1).type(*).id = 'tutorial';
instance-of($TUTORIAL, tutorial), publication-date($TUTORIAL, $DATE) order by $DATE desc?
Retrieve a list of documents, sorted by publication date (ascending), only number 3 to 5
function test (map $m, string $from := "3", string $to := "5") as list function alldocs (map $m) as list return { forall $t [ $d (document) bn: $head ] in $m return ($#, $head, "$t/in(publication-date)") sort by $t/in(publication-date) asc } return { alldocs ($m) }["{$from}" .. "{$to}"]
list{ for $Pub at $i in /topic[*;roleOf::opus[is-author-of]/role::author] order by !$Pub/oc::publication-date ascending offset 3 limit 3 return list{$i, !$Pub/bn::*, !$Pub/oc::publication-date} }
select $document.bn, $document.oc(publication-date) where exists $document.oc(publication-date) order by $document.oc(publication-date) limit 3 offset 2;
/* can't produce a row number column */ instance-of($DOCUMENT, document), publication-date($DOCUMENT, $PUBDATE) order by $PUBDATE limit 3 offset 2?
Retrieve all topic identifiers of documents which have a download URL
function test (map $m) as list return $m / document [ ./oc (download) ]
list{ for $Doc in /topic[*;roleOf::opus[is-author-of]/role::author and oc::download] return !$Doc/id }
select $topic.id where exists $topic.oc(download).rr;
select $DOCUMENT from instance-of($DOCUMENT, document), download($DOCUMENT, $URL)?
Retrieve a list of author's email addresses where the author has authored documents for which no download URL exists
function test (map $m) as list return $m / is-author-of [not ./opus/oc(download)] < ./ author / oc(email) , ./opus >
list{ for $Author in /topic[*;roleOf::author[is-author-of]/role::opus[*;not(oc::download)] ] for $Pub in $Author/roleOf::author[is-author-of]/role::opus[*;not(oc::download)] return list{!$Author/oc::email,!$Pub/id} }
select $author.oc(email) where is-author-of->author = $author and is-author-of->opus = $opus and not exists $opus.oc(download).rr;
select $EMAIL from is-author-of($AUTHOR : author, $DOCUMENT : opus), email($AUTHOR, $EMAIL), not(download($DOCUMENT, $URL))?
Retrieve a list of author names where the author has written more than 1 document
function test (map $m) as list return { forall [ $p (person) ] in $m return { if fn:count ($p -> author \ is-author-of) > 1 then ($bn) } }
list{ for $Author in /topic[*;count(roleOf::author[is-author-of]/role::opus)>1] return !$Author/bn::* }
select $author.bn@uc where is-author-of->author = $author and is-author-of->opus = $document1 and $association->author = $author and $association->opus = $document2 and $association = 'is-author-of' and $document1 != $document2;
select $AUTHOR from is-author-of($AUTHOR : author, $DOCUMENT1 : opus), is-author-of($AUTHOR : author, $DOCUMENT2 : opus), $DOCUMENT1 /= $DOCUMENT2?
A list of author names where the author has not written a single document with someone else
function test (map $m) as list return $m / is-author-of / author [ fn:count (. -> is-author-of) < 2 ] / bn
list{ for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] let $Pubs := $Author/roleOf::author[is-author-of]/role::opus where every $Pub in $Pubs satisfies not($Pub/roleOf::opus[is-author-of]/role::author!=$Author) return !$Author/bn::* }
select $author1.bn where is-author-of->author = $author1 and is-author-of->opus = $document and not ($association->author = $author2 and $association->opus = $document and $association = 'is-author-of' and $author1 != $author2);
select $AUTHOR1 from is-author-of($AUTHOR1 : author, $DOCUMENT : opus), not(is-author-of($AUTHOR2 : author, $DOCUMENT : opus), $AUTHOR1 /= $AUTHOR2)?
Retrieve all topic identifiers of documents and their URLs which have a non-working URL at query time
function test (map $m) as list declare namespace http="http://astma.it.bond.edu.au/ns/query/ext/http" return { forall [ $d (document) oc (download) : $url ] in $m return { if not http:head ($url) then ($d, $url) } }
list{ for $Doc in /topic[*;roleOf::opus[is-author-of]/role::author and oc::download] where not(isWorkingURI($Doc/oc::download)) return list{!$Doc/id,!$Doc/oc::download} }
select $document.id where is-author-of->opus = $document and not retrievable($document.oc(download));
import "http://psi.ontopia.net/tolog/experimental/" as exp instance-of($DOCUMENT, document), subject-locator($DOCUMENT, $URI), not(exp:retrievable($URI))?
Retrieve all topic identifiers for documents for which the abstract in english (i.e. the occurrence of type abstract in scope en) contains the phrase 'topic map' or 'topic maps', case-insensitive
function test (map $m) as list return { forall [ $d (document) in @ en (abstract) : $abstract =~ /topic maps?/i ] in $m return ($d, $abstract) }
list{ for $Doc in /topic[*;roleOf::opus[is-author-of]/role::author] where contains($Doc/oc::abstract@en,("topic map","topic maps")) return !$Doc/id }
# strange - the following doesn't give anything select $document.id where is-author-of->opus = $document and $document.oc(abstract)@en.rd ~* 'topic maps?';
import "http://psi.ontopia.net/tolog/string/" as str instance-of($DOCUMENT, document), occurrence($DOCUMENT, $OCC), type($OCC, abstract), scope($OCC, en), value($OCC, $ABSTRACT), str:lowercase($ABSTRACT, $abstract), str:contains($abstract, "topic map")?
Retrieve all documents which have a title in german
function test (map $m) as list return { forall [ $d (document) bn @ de : $head ] in $m return ($d, $head) }
list{ for $Doc in /topic[*;roleOf::opus[is-author-of]/role::author] where $Doc/bn::*@de return !$Doc/id }
select $document.id where is-author-of->opus = $document and exists $document.bn@de;
select $DOCUMENT from instance-of($DOCUMENT, document), topic-name($DOCUMENT, $NAME), scope($NAME, de)?
Retrieve all topic identifiers of the pairs of documents which share at least one word in the title, ignoring stopwords like 'and', 'of', 'the'
function test (map $m) as list declare namespace ex="http://astma.it.bond.edu.au/ns/query/ext/example" return { forall [ $d1 (document) bn: $title1 ] => exists [ $d2 (document) bn: $title2 ] in $m return { if ex:hasCommonWord ({$title1}, {$title2}, "the", "and", "of") then ($d1, $d2) } unique sort by $d1, $d2 }
list{ let $StopList:=("and","of","the") for $Doc1 in /topic[*;roleOf::opus[is-author-of]/role::author] for $Doc2 in /topic[*;roleOf::opus[is-author-of]/role::author] let $WordList1:=split(!$Doc1::bn:*) except $StopList let $WordList2:=split(!$Doc2::bn:*) except $StopList where not(empty($WordList1 intersect $WordList2)) return list {!$Doc1/id,!$Doc2/id} }
select $document1.id where is-author-of->opus = $document1 and $association->opus = $document2 and $association = 'is-author-of' and commonWords($document1.bn, $document2.bn, 'and', 'of', 'the') >= 1;
Retrieve the identifiers of all topics which represent information resources on the ontopia.net server(s)
function test (map $m) as list return { forall [ $d (document) reifies $url =~ /ontopia\.net/ ] in $m return ($d) }
list{ for $Doc1 in /topic[*;match(subl,".*ontopia\.net.*")] return !$Doc1/id }
select $topic.id where $topic.si.rr ~* 'ontopia.net/';
import "http://psi.ontopia.net/tolog/string/" as str select $TOPIC from subject-locator($TOPIC, $URI), str:contains($URI, "ontopia.net/")?
Retrieve the topic identifiers of all documents which are not written in the language English
function test (map $m) as list return { forall [ $d (document) !in (language) : english ] in $m return ($d) }
list{ for $Doc1 in /topic[*,roleOf::opus[is-author-of]/role::author and not(oc::language="English")] return !$Doc1/id }
select $document.id where is-author-of->opus = $document and $document.oc(language) != 'english'; The above syntax is implemented in the prototype but fails because of the bug with negation. So, for example, the opposite query is possible: select $document.id where is-author-of->opus = $document and $document.oc(language) = 'english';
instance-of($DOCUMENT, document), not(language($DOCUMENT, "english"))?
Retrieve the topic identifiers of all documents which are directly or indirectly influenced by something which Steve Pepper wrote
function test (map $m, string $influencer) as list # returns a list of docs which are influenced by $e, recursive function influents (string $e) as list return { forall [ (is-influenced-by) influence : $e influenced: $d ] return {$d + influents($d)} } return { forall [ (is-author-of) opus : $d author : $influencer ] return { forall $e in influents($d) return { ($d, "influenced by", $e) } } }
[transitive=true] define step has-influence-on() { $$self/roleOf::target@$$scope[influenced-by]/role::source } define step authored-by() { $$self/roleOf::opus@$$scope[is-author-of]/role::author } list{ for $Doc1 in /topic[*; authored-by=pepper] let $Docs:=$Doc1//has-influence-on for $Doc2 in $Docs where not(empty($Docs)) order by !$Doc2/id return list{!$Doc2/id,'influenced by',!$Doc1/id} }
OK, this is quite pre-mature issue in Toma. I am not sure yet exactly how functions will be used. In the following example, I use the rule that functions can take only strings as input (and not objects). Probably this should be changed (although this simplifies things). define all_influenced_by(&influence_id) { select $influenced.id where is-influenced-by->influenced = $mid and is-influenced-by->influence = $influence and $influence.id = '&influence_id' and ($influenced = $mid or $influenced = all_influenced_by($mid.id)); } select $influenced.id where is-author-of->opus = $influence and is-author-of->author.bn@uc = 'Steve Pepper' and all_influenced_by($influence.id) = $influenced;
indirect-influence($INFLUENCED, $INFLUENCE) :- { is-influenced-by($INFLUENCED : influenced, $INFLUENCE : influence) | is-influenced-by($INFLUENCED : influenced, $MID : influence), indirect-influence($MID, $INFLUENCE) }. indirect-influence($INFLUENCED, $INFLUENCE), is-author-of($INFLUENCE : opus, steve-pepper : author)?
Retrieve all identifiers of topics which are either instances of paper or tutorial
function test (map $m) as list return { forall [ $d (tutorial | paper) ] in $m return ($d) unique }
list{ for $Doc in /topic[paper|tutorial] return !$Doc/id }
# it is not totally clear to me what is the meaning by sub class # and super class in the context of this exercise. from other # solutions I understand that you have hirarchy of instanceOf # (so the operator to find the isntanceOf is used also for # super-classes - sub-classes relationship, but I thought that # this should be a different operator (as it is different # relationship). select $topic.id where $topic.type(1).id in ('journal-paper', 'conference-paper', 'tutorial');
{ instance-of($DOCUMENT, tutorial) | instance-of($DOCUMENT, paper) }?
Retrieve all titles of all publications (regardless their scope) together with their most specific class
function test (map $m) as list return { forall [ $d ($closest) ] => forall [ $d ($type) ] # remember: different variables -> different values! => not exists [ (is-subclass-of) superclass: $closest subclass : $type ] in $m return ($d/bn, $closest) }
list{ for $Doc in /topic[document] return List{!$Doc/bn::*,!$Doc/type} }
# this query behave differently from what is expected in # http://www.isotopicmaps.org/tmql/use-cases.html#d0e805 # but I could not find title of pepper99a in German in # http://www.isotopicmaps.org/tmql/uc-literature.atm # so this query must be correct. select $document.bn, $type.id where is-author-of->opus = $document and $document.type(1) = $type;
instance-of($DOCUMENT, document), direct-instance-of($DOCUMENT, $CLASS), topic-name($DOCUMENT, $TITLE)?
Retrieve all authors
function test (map $m) as list return ({$m / is-author-of / author})
for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] return topic($Author){}
select $author.id where is-author-of->author = $author;
select $AUTHOR from is-author-of($AUTHOR : author, $WORK : opus)?
Retrieve all basename items of authors
function test (map $m) as list return ({$m / is-author-of / author / bn})
for $BaseName in /topic[*;roleOf::author[is-author-of]/role::opus]/bn return baseName($BaseName){}
select $author.bn@uc where is-author-of->author = $author;
select $TNAME from is-author-of($AUTHOR : author, $WORK : opus), topic-name($AUTHOR, $TNAME)?
Retrieve a list of all occurrence items being of type email
function test (map $m) as list return ({$m / is-author-of / author / oc(email)})
for $Occurrence in /topic[*]/oc[email] return occurrence($Occurrence){}
select $topic.oc(email) where exists $topic.oc(email);
select $OCC from occurrence($TOPIC, $OCC), type($OCC, email)?
Return all titles of papers together with the author names
function test (map $m) as xml return <papers>{ forall [ $d (paper) ] in $m return <paper id="{$d}"> <head>{$d/bn}</head>{ forall [ (is-author-of) opus : $d author : $a ] => exists [ $a (person) bn @ sort : $name ] in $m return <author>{$name}</author>} </paper> }</papers>
<papers> { for $Doc in /topic[paper] return <paper> <head>{!$Doc/bn::*}</head> { for $Author in $Doc/roleOf::opus[is-author-of]/role::author return <author>{!$Author/bn::*}</author> } </paper> } </papers>
As stated in the mailing list, I would prefer to see the creation of XML outside of the language. However, as it was requested in this document, I provide one way to implement XML generation: define papers() { select $paper.id as paper_id, and $paper.bn[1] as paper_title where $paper.type(1) = 'conference-paper'; } define paper_authors(&paper_id) { select $author.bn[1] as author, where is-author-of->author = $author and id-author-of->opus.id = &paper_id } process skin { <papers> <while query="papers()"> <paper id="&paper_id"> <head>&paper_title</head> <while query="paper_authors(&paper_id)"> <author>$author</author> </while> </paper> </while> </papers> }
<tmtl:page xmlns:tmtl="http://psi.ontopia.net/tmtl/"> <papers> <tmtl:foreach select="instance-of($PAPER, paper), name($PAPER, $TITLE)?"> <paper> <head>{$TITLE}</head> <tmtl:foreach select="is-author-of($AUTHOR : author, %PAPER% : opus), name($AUTHOR, $NAME)?"> <author>{$NAME}</author> </tmtl:foreach> </paper> </tmtl:foreach> </papers> </tmtl:page>
Return the name(s) of all authors who have authored more than one paper
function test (map $m) as xml return <recidivists>{ forall [ (is-author-of) opus : $d1 author : $a ] => forall [ (is-author-of) opus : $d2 author : $a ] => exists [ $a (person) ] in $m return <author>{$a/bn}</author> }</recidivists>
<recidivists> { for $Author in /topic[*; count(roleOf::author[is-author-of]/role::opus[paper])>1] return <author>{!$Author/bn::*}</author> } </recidivists>
define hardworking_authors() { select $author.bn as author where 1 < (select count($document) where is-author-of->author = $author and is-author-of->opus = $document group by $author); } process skin { <recidivists> <while query="hardworking_authors()"> <author>&author</author> </while> </recidivists> }
<tmtl:page xmlns:tmtl="http://psi.ontopia.net/tmtl/"> <recidivists ><tmtl:foreach select="select $NAME from is-author-of($AUTHOR : author, $WORK1 : opus), is-author-of($AUTHOR : author, $WORK2 : opus), $WORK1 /= $WORK2, name($AUTHOR, $NAME)?"> <author>{$NAME}</author> </tmtl:foreach ></recidivists> </tmtl:page>
Select only the tutorial documents from the topic map and return an RDF document containing the title and the author information
function test (map $m) as xml return <rdf:RDF xmlns:rdf="http://www.w3c.org/RDF/" xmlns:lit="http://www.isotopicmaps.org/tmql/use-cases/literature/">{ forall [ $d (tutorial) bn: $title oc (download): $url ] in $m return <lit:tutorial rdf:about="{$url}"> <lit:title>{$title}</lit:title>{ forall [ (is-author-of) author : $a opus : $d ] return <lit:author>{$a/bn}</lit:author> } </lit:tutorial> } </rdf:RDF>
<rdf:RDF xmlns:rdf="http://www.w3c.org/RDF/" xmlns:lit="http://www.isotopicmaps.org/tmql/use-cases/literature/"> { for $Tutorial in /topic[tutorial], for $Author in $Tutorial/roleOf::opus[is-author-of]/role::author return <lit:tutorial rdf:about="{!$Tutorial/subl}"> <lit:title>{!$Tutorial/bn::*}</lit:title> <lit:author>{!$Author/bn::*}</lit:author> </lit:tutorial> } </rdf:RDF>
define tutorials() { select $tutorial.title[1] as title, $author.bn[1] as author, $tutorial.oc(download) as uri where $tutorial.type(1).id = 'tutorial' and is-author-of->opus = $tutorial and is-author-of->author = $author; } process skin { <rdf:RDF xmlns:rdf="http://www.w3c.org/RDF/"; xmlns:lit="http://www.isotopicmaps.org/tmql/use-cases/literature/"> <while query="tutorials()"> <lit:tutorial rdf:about="&uri"> <lit:title>&title</lit:title> <lit:author>&author</lit:author> </lit:tutorial> </while> </rdf> }
<tmtl:page xmlns:tmtl="http://psi.ontopia.net/tmtl/"> <rdf:RDF xmlns:rdf="http://www.w3c.org/RDF/" xmlns:lit="http://www.isotopicmaps.org/tmql/use-cases/literature/"> <tmtl:foreach select="instance-of($TUTORIAL, tutorial), is-author-of($TUTORIAL : opus, $AUTHOR : author), name($TUTORIAL, $TITLE), name($AUTHOR, $NAME), subject-locator($TUTORIAL, $URI)?"> <lit:tutorial rdf:about="{$URI}"> <lit:title>{$TITLE}</lit:title> <lit:author>{$NAME}</lit:author> </lit:tutorial> </tmtl:foreach> </rdf:RDF> </tmtl:page>
Return all persons with their name and a bibliography as nested elements
function test (map $m) as xml return <persons>{ forall [ $p (person) ] in $m return <person id="{$p}"> <name>{$p/bn}</name> <bibliography>{ forall [ (is-author-of) author : $p opus : $d ] return <publication>{$d/bn} ({$d/in(language) or else 'unknown'})</publication> sort by $d/in(publication-date) desc }</bibliography> </person> </persons>
<persons> { for $Person in /topic[person] let $Name:=$Person/bn::*@sort let $Pubs:=$Person/roleOf::author[is-author-of]/role::opus return <person id="{!$Person/id}"> <name>{!$Name}</name> <bibliography> { for $Pub in $Pubs return <publication>{!$Pub/bn::*} { if ($Pub/oc::language) then !$Pub/oc::language else "(unknown)" } </publication> } </bibliography> </person> } </persons>
define persons() { select $person.id as person_id, $person.bn[1] as person_name where $person.type(1).id = 'person'; } define publications_of_person(&person_id) { select $publication.bn[1] as publication_title $publication.oc(language) as publication_language where is-author-of->opus = $publication and is-author-of->author.id = '&person_id'; } process skin { <persons> <while query="persons()"> <person id="&person_id"> <name>&person_name</name> <bibliography> <while query="publications_of_person(&person_id)"> <publication> &publication_title <if condition="&publication_language">&publication_language</if> <else>unknown</else> </publication> </while> </bibliography> </person> </while> </persons>
<tmtl:page xmlns:tmtl="http://psi.ontopia.net/tmtl/"> <persons> <tmtl:foreach select="instance-of($PERSON, person), topic-name($PERSON, $TNAME), scope($TNAME, sort), value($TNAME, $NAME)?"> <person id="{$PERSON}"> <name>{$NAME}</name> <bibliography> <tmtl:foreach select="is-author-of(%PERSON% : author, $WORK : opus), name($WORK, $TITLE)?"> <publication>{$TITLE} (<tmtl:if select="language(%WORK%, $LANG)?" >{$LANG}</tmtl:if ><tmtl:if select="not(language(%WORK%, $LANG))?" >unknown</tmtl:if>)</publication> </tmtl:foreach> </bibliography> </person> </tmtl:foreach> </persons> </tmtl:page>
Journal paper with author associations and publication-date occurrences redone as associations
function test (map $m) as map return { forall [ $j (journal-paper) ] return {$j} (journal-paper) bn: {$j/bn} {$j/oc} # clone all url occurrences {$j/in} # clone all internal occurrences (was-published-in) date : x-dates-{$j/in(publication-date)} document : $j { forall $a [ (is-author-of) opus : $j ] return {$a/*} # clone the whole node } }
Documents with cite codes reclassified and ternary associations generated
function test (map $m) as map return { forall [ $j (document) oc (cite-code): $cite ] return { forall [ $j (document) ] return {$j} ({if $j -> is-a conference-paper then 'publication' else if $j -> is-a journal-paper then 'publication' else 'no-publication'}) {$j/*} # clone all basenames, url occurrences, all resourceData { if $j/in(publication-date) then (is-published-by) document : {$j} publisher : prints-are-us date : urn:x-date-{$j/in(publication-date)} else (is-published-by) document : {$j} publisher : prints-are-us } } }