ISO/IEC JTC 1/SC 34N0492

ISO/IEC logo

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 Chairman)
Y-12 National Security Complex
Bldg. 9113, M.S. 8208
Oak Ridge, TN 37831-8208 U.S.A.
Telephone: +1 865 574-6973
Facsimile: +1 865 574-1896
Network: [email protected]
http://www.y12.doe.gov/sgml/sc34/
ftp://ftp.y12.doe.gov/pub/sgml/sc34/

Mr. G. Ken Holman
(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
       }
}
}