
| 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
}
}
}