ISO/IEC JTC 1/SC 34N0492
ISO/IEC JTC 1/SC 34
Information Technology --
Document Description and Processing Languages
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: [email protected] http://www.jtc1sc34.org |
TMQL Use Case Solutions
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.
5.2.2.01
Retrieve all author names
AsTMa?
function test (map $m) as list return ($m / is-author-of / author/bn @uc)
TMPath
list { for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] return $Author/bn::*[1] }
Toma
select $author.bn@uc where is-author-of->author = $author;
tolog
select $NAME from is-author-of($AUTHOR : author, $WORK : opus), name($AUTHOR, $NAME)?
5.2.2.02
Retrieve all author names sorted
AsTMa?
function test (map $m) as list return ($m / is-author-of / author /bn@uc) unique sort by $a/bn@sort
TMPath
list{ for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] order by $Author/bn::*@sort[1] return $Author/bn::*[1] }
Toma
select $author.bn@uc where is-author-of->author = $author order by $author.bn@sort;
tolog
select $AUTHOR from is-author-of($AUTHOR : author, $WORK : opus) order by $AUTHOR?
5.2.2.03
Retrieve the titles of all tutorials. The titles should be preferably those in scope en, de or in the unconstrained scope, in that order.
AsTMa?
function test (map $m) as list return { forall $t [ $d (tutorial) bn @ (en | de | uc): $title ] in $m return ($title) }
TMPath
list{ for $Tutorial in /topic[tutorial] return ( $Tutorial/bn::*@en[1], $Tutorial/bn::*@de[1], $Tutorial/bn::*[1]) }
Toma
select $topic.bn@$scope where $topic.type(1).id = 'tutorial' and exists $topic.bn@$scope and $scope.id in ('en', 'de', 'uc');
5.2.2.04
Retrieve the names of all persons who have not authored anything
AsTMa?
function test (map $m) as list return $m / person [ not . -> author \ is-author-of ] / bn
TMPath
list{ for $Person in /topic[person;not(roleOf::author[is-author-of]/role::opus)] return $Person/bn::*[1] }
Toma
select $person.bn@uc where is-author-of->author != $person and $person.type(1).id = 'person';
tolog
select $PERSON from instance-of($PERSON, person), not(is-author-of($PERSON : author, $WORK : opus))?
5.2.2.05
Retrieve a list of all author names together with the title of their publications
AsTMa?
function test (map $m) as list return $m / is-author-of < . / author / bn@sort , . / opus / bn >
TMPath
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]} }
Toma
select $author.bn@uc, $opus.bn where is-author-of->author = $author and is-author-of->opus = $opus;
tolog
is-author-of($PERSON : author, $WORK : opus)?
5.2.2.06
Retrieve a list of all titles of documents which are tutorials, sorted by publication date, descending
AsTMa?
function test (map $m) as list return $m / tutorial < ./bn, ./in(publication-date) sort by ./in(publication-date) desc >
TMPath
list{ for $Pub in /topic[tutorial] order by !$Pub/oc::publication-date descending return list{!$Pub/bn::*,!$Pub/oc::publication-date} }
Toma
select $tutorial.bn where $tutorial.type(1).type(*).id = 'tutorial';
tolog
instance-of($TUTORIAL, tutorial), publication-date($TUTORIAL, $DATE) order by $DATE desc?
5.2.2.07
Retrieve a list of documents, sorted by publication date (ascending), only number 3 to 5
AsTMa?
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}"]
TMPath
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} }
Toma
select $document.bn, $document.oc(publication-date) where exists $document.oc(publication-date) order by $document.oc(publication-date) limit 3 offset 2;
tolog
/* can't produce a row number column */ instance-of($DOCUMENT, document), publication-date($DOCUMENT, $PUBDATE) order by $PUBDATE limit 3 offset 2?
5.2.2.08
Retrieve all topic identifiers of documents which have a download URL
AsTMa?
function test (map $m) as list return $m / document [ ./oc (download) ]
TMPath
list{ for $Doc in /topic[*;roleOf::opus[is-author-of]/role::author and oc::download] return !$Doc/id }
Toma
select $topic.id where exists $topic.oc(download).rr;
tolog
select $DOCUMENT from instance-of($DOCUMENT, document), download($DOCUMENT, $URL)?
5.2.2.09
Retrieve a list of author's email addresses where the author has authored documents for which no download URL exists
AsTMa?
function test (map $m) as list return $m / is-author-of [not ./opus/oc(download)] < ./ author / oc(email) , ./opus >
TMPath
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} }
Toma
select $author.oc(email) where is-author-of->author = $author and is-author-of->opus = $opus and not exists $opus.oc(download).rr;
tolog
select $EMAIL from is-author-of($AUTHOR : author, $DOCUMENT : opus), email($AUTHOR, $EMAIL), not(download($DOCUMENT, $URL))?
5.2.2.10
Retrieve a list of author names where the author has written more than 1 document
AsTMa?
function test (map $m) as list return { forall [ $p (person) ] in $m return { if fn:count ($p -> author \ is-author-of) > 1 then ($bn) } }
TMPath
list{ for $Author in /topic[*;count(roleOf::author[is-author-of]/role::opus)>1] return !$Author/bn::* }
Toma
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;
tolog
select $AUTHOR from is-author-of($AUTHOR : author, $DOCUMENT1 : opus), is-author-of($AUTHOR : author, $DOCUMENT2 : opus), $DOCUMENT1 /= $DOCUMENT2?
5.2.2.11
A list of author names where the author has not written a single document with someone else
AsTMa?
function test (map $m) as list return $m / is-author-of / author [ fn:count (. -> is-author-of) < 2 ] / bn
TMPath
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::* }
Toma
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);
tolog
select $AUTHOR1 from is-author-of($AUTHOR1 : author, $DOCUMENT : opus), not(is-author-of($AUTHOR2 : author, $DOCUMENT : opus), $AUTHOR1 /= $AUTHOR2)?
5.2.2.12
Retrieve all topic identifiers of documents and their URLs which have a non-working URL at query time
AsTMa?
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) } }
TMPath
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} }
Toma
select $document.id where is-author-of->opus = $document and not retrievable($document.oc(download));
tolog
import "http://psi.ontopia.net/tolog/experimental/" as exp instance-of($DOCUMENT, document), subject-locator($DOCUMENT, $URI), not(exp:retrievable($URI))?
5.2.2.13
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
AsTMa?
function test (map $m) as list return { forall [ $d (document) in @ en (abstract) : $abstract =~ /topic maps?/i ] in $m return ($d, $abstract) }
TMPath
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 }
Toma
# strange - the following doesn't give anything select $document.id where is-author-of->opus = $document and $document.oc(abstract)@en.rd ~* 'topic maps?';
tolog
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")?
5.2.2.14
Retrieve all documents which have a title in german
AsTMa?
function test (map $m) as list return { forall [ $d (document) bn @ de : $head ] in $m return ($d, $head) }
TMPath
list{ for $Doc in /topic[*;roleOf::opus[is-author-of]/role::author] where $Doc/bn::*@de return !$Doc/id }
Toma
select $document.id where is-author-of->opus = $document and exists $document.bn@de;
tolog
select $DOCUMENT from instance-of($DOCUMENT, document), topic-name($DOCUMENT, $NAME), scope($NAME, de)?
5.2.2.15
Retrieve all topic identifiers of the pairs of documents which share at least one word in the title, ignoring stopwords like 'and', 'of', 'the'
AsTMa?
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 }
TMPath
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} }
Toma
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;
5.2.2.16
Retrieve the identifiers of all topics which represent information resources on the ontopia.net server(s)
AsTMa?
function test (map $m) as list return { forall [ $d (document) reifies $url =~ /ontopia\.net/ ] in $m return ($d) }
TMPath
list{ for $Doc1 in /topic[*;match(subl,".*ontopia\.net.*")] return !$Doc1/id }
Toma
select $topic.id where $topic.si.rr ~* 'ontopia.net/';
tolog
import "http://psi.ontopia.net/tolog/string/" as str select $TOPIC from subject-locator($TOPIC, $URI), str:contains($URI, "ontopia.net/")?
5.2.2.17
Retrieve the topic identifiers of all documents which are not written in the language English
AsTMa?
function test (map $m) as list return { forall [ $d (document) !in (language) : english ] in $m return ($d) }
TMPath
list{ for $Doc1 in /topic[*,roleOf::opus[is-author-of]/role::author and not(oc::language="English")] return !$Doc1/id }
Toma
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';
tolog
instance-of($DOCUMENT, document), not(language($DOCUMENT, "english"))?
5.2.2.18
Retrieve the topic identifiers of all documents which are directly or indirectly influenced by something which Steve Pepper wrote
AsTMa?
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) } } }
TMPath
[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} }
Toma
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;
tolog
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)?
5.2.2.19
Retrieve all identifiers of topics which are either instances of paper or tutorial
AsTMa?
function test (map $m) as list return { forall [ $d (tutorial | paper) ] in $m return ($d) unique }
TMPath
list{ for $Doc in /topic[paper|tutorial] return !$Doc/id }
Toma
# 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');
tolog
{ instance-of($DOCUMENT, tutorial) | instance-of($DOCUMENT, paper) }?
5.2.2.20
Retrieve all titles of all publications (regardless their scope) together with their most specific class
AsTMa?
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) }
TMPath
list{ for $Doc in /topic[document] return List{!$Doc/bn::*,!$Doc/type} }
Toma
# 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;
tolog
instance-of($DOCUMENT, document), direct-instance-of($DOCUMENT, $CLASS), topic-name($DOCUMENT, $TITLE)?
5.2.2.21
Retrieve all authors
AsTMa?
function test (map $m) as list return ({$m / is-author-of / author})
TMPath
for $Author in /topic[*;roleOf::author[is-author-of]/role::opus] return topic($Author){}
Toma
select $author.id where is-author-of->author = $author;
tolog
select $AUTHOR from is-author-of($AUTHOR : author, $WORK : opus)?
5.2.2.22
Retrieve all basename items of authors
AsTMa?
function test (map $m) as list return ({$m / is-author-of / author / bn})
TMPath
for $BaseName in /topic[*;roleOf::author[is-author-of]/role::opus]/bn return baseName($BaseName){}
Toma
select $author.bn@uc where is-author-of->author = $author;
tolog
select $TNAME from is-author-of($AUTHOR : author, $WORK : opus), topic-name($AUTHOR, $TNAME)?
5.2.2.23
Retrieve a list of all occurrence items being of type email
AsTMa?
function test (map $m) as list return ({$m / is-author-of / author / oc(email)})
TMPath
for $Occurrence in /topic[*]/oc[email] return occurrence($Occurrence){}
Toma
select $topic.oc(email) where exists $topic.oc(email);
tolog
select $OCC from occurrence($TOPIC, $OCC), type($OCC, email)?
5.3.1
Return all titles of papers together with the author names
AsTMa?
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>
TMPath
<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>
Toma
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> }
tolog
<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>
5.3.2
Return the name(s) of all authors who have authored more than one paper
AsTMa?
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>
TMPath
<recidivists> { for $Author in /topic[*; count(roleOf::author[is-author-of]/role::opus[paper])>1] return <author>{!$Author/bn::*}</author> } </recidivists>
Toma
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> }
tolog
<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>
5.3.3
Select only the tutorial documents from the topic map and return an RDF document containing the title and the author information
AsTMa?
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>
TMPath
<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>
Toma
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> }
tolog
<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>
5.3.4
Return all persons with their name and a bibliography as nested elements
AsTMa?
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>
TMPath
<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>
Toma
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>
tolog
<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>
5.4.1
Journal paper with author associations and publication-date occurrences redone as associations
AsTMa?
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 } }
5.4.2
Documents with cite codes reclassified and ternary associations generated
AsTMa?
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 } } }