Commit 7246d7d8 authored by Mathias Goebel's avatar Mathias Goebel 🎠
Browse files

Merge branch 'release/4.3.0'

parents 50cf2b2b 068f1ba5
......@@ -19,7 +19,7 @@ For a new up and running instance two commands are needed:
ant test &&
bash test/eXist-db-*/bin/startup.sh
```
This will result in local instance at [localhost:8080](http://localhost:8080/exist/).
This will result in a local instance at [localhost:8080](http://localhost:8080/exist/).
CAUTION: A new build will remove the instance!
......
project.name=http://textgrid.de/ns/SADE-fontane-develop
project.version=4.2.1
project.version=4.3.0
project.title=[Fontane] SADE
project.abbrev=SADE-fontane-develop
project.processorversion=4.6.1
......
......@@ -140,7 +140,7 @@ else if (contains($exist:path, "/api/")) then
<redirect url="/exist/restxq/api/{$path}"/>
</dispatch>
else if (contains($exist:path, "/openapi/")) then
else if (contains($exist:path, "/doc/api/") or contains($exist:path, "/openapi/")) then
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<forward url="/openapi/{ $exist:path => substring-after("/openapi/") => replace("json", "xq") }" method="get">
<add-parameter name="target" value="{ substring-after($exist:root, "://") || $exist:controller }"/>
......
xquery version "3.1";
(:~
: This module is responsible for pulling the whole transformation/serialization
: of the edited text together.
:
: It creates all the single HTML files for each notebook as well as a complete
: intermediate format TEI/XML that is used for the print output.
:
: @author Michelle Weidling
: @version 1.0
:)
module namespace etTransfo="http://fontane-nb.dariah.eu/etTransfo";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare namespace xi="http://www.w3.org/2001/XInclude";
import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm";
import module namespace fontaneSimple="http://fontane-nb.dariah.eu/teisimple" at "tei2teisimple.xqm";
import module namespace fsort="http://fontane-nb.dariah.eu/sort" at "sort.xqm";
import module namespace functx = "http://www.functx.com";
import module namespace prepCom="http://fontane-nb.dariah.eu/prepCom" at "prepcom.xqm";
import module namespace presort="http://fontane-nb.dariah.eu/presort" at "presort.xqm";
import module namespace simple2xhtml="http://fontane-nb.dariah.eu/simple2xhtml" at "simple2xhtml.xqm";
import module namespace tidySimple ="http://fontane-nb.dariah.eu/tidysimple" at "tidysimple.xqm";
declare variable $etTransfo:cases :=
(
"3qtcz.xml", (: case C :)
"3qtqv.xml" (: case A :)
(: "3qtqw.xml" (: case B :) :)
(: "3qtqx.xml" (: case D :):)
(: "3qtqz.xml" (: case E :):)
);
(:~
: The main function
:
: @author Michelle Weidling
: @return An XHTML page for each notebook in /db/sade-projects/textgrid/data/print/xhtml
: @return An intermediate TEI/XML with all notebooks in it in /db/sade-projects/textgrid/data/print/xml/fontane-full.xml
:)
declare function etTransfo:complete() {
for $case in $etTransfo:cases return
(etTransfo:create-case($case),
etTransfo:create-htmls($case)),
try {
etTransfo:create-print-tei()
} catch * {
error(QName("error", "ETTRANSFO02"), "An error occured while creating the whole TEI base for print.")
}
};
declare function etTransfo:transform-on-publish($notebook) {
try {
etTransfo:transform-tei($notebook//tei:TEI)
} catch * {
error(QName("error", "ETTRANSFO05"), "Could not transform " || $notebook//tei:title[1]/string() || " to XHTML.")
}
};
(:~
: Resolves all XIncludes in a given case file and copies all notebooks belonging to a case into one file.
:
: @author Michelle Weidling
: @param $showcase The filename of a showcase, e.g. "12345.xml"
: @return The full path to the created showcase with all notebooks in it.
:)
declare function etTransfo:create-case($showcase as xs:string) as xs:string {
let $doc :=
try {
doc("/db/sade-projects/textgrid/data/xml/data/" || $showcase)
} catch * {
error(QName("error", "ETTRANSFO03"), "An error occured while opening " || $showcase || ".")
}
let $new-filename := $doc//tei:title[1] => replace(" ", "-") || ".xml"
let $assure-dir-available :=
if(xmldb:collection-available($config:data-root || "/print/")) then
()
else
(xmldb:create-collection($config:data-root, "/print"),
xmldb:create-collection($config:data-root || "/print/", "xml"),
xmldb:create-collection($config:data-root || "/print/", "xhtml"))
let $create-new-file := xmldb:store($config:data-root || "/print/xml/", $new-filename, $doc/*)
let $xis := doc($create-new-file)//xi:include
let $update :=
for $xi in $xis
let $uri := $xi/@href/string()
let $tei-referred-to :=
try {
doc("/db/sade-projects/textgrid/data/xml/data/" || $uri || ".xml")/tei:TEI
} catch * {
error(QName("error", "ETTRANSFO04"), "Couldn't find the node tei:TEI of " || $uri || ".")
}
let $updated-notebook :=
element {QName("http://www.tei-c.org/ns/1.0", "TEI")} {
attribute id {$uri},
$tei-referred-to/@*,
$tei-referred-to/*
}
return update replace $xi with $updated-notebook
return
$create-new-file
};
(:~
: Gets all notebooks of a showcase in-memory.
:
: @author Michelle Weidling
: @param $showcase The filename of a showcase, e.g. "12345.xml"
: @return All notebooks of a showcase in-memory, i.e. a sequence of tei:TEI
:)
declare function etTransfo:get-teis($showcase as xs:string) as element(tei:TEI)+ {
let $doc := doc("/db/sade-projects/textgrid/data/xml/data/" || $showcase)
let $summary-file-name := $doc//tei:title[1] => replace(" ", "-") || ".xml"
let $summary-file :=
try {
doc($config:data-root || "/print/xml/" || $summary-file-name)
} catch * {
error(QName("error", "ETTRANSFO04"), "Summary file for case " || $showcase || "couldn't be opened.")
}
return
$summary-file//tei:TEI
};
(:~
: Creates the intermediate format of a given case and transforms each notebook of a showcase to a XHTML page.
:
: @author Michelle Weidling
: @param $showcase The filename of a showcase, e.g. "12345.xml"
: @return One or more strings indicating the location where the XHTML(s) have been stored to.
:)
declare function etTransfo:create-htmls($showcase as xs:string) as xs:string+ {
let $teis := etTransfo:get-teis($showcase)
for $tei in $teis return
etTransfo:transform-tei($tei)
};
declare function etTransfo:transform-tei($tei as element(tei:TEI)) {
fsort:main($tei)
=> prepCom:main($tei/@id)
=> fontaneSimple:main($tei/@id)
=> tidySimple:main($tei/@id)
(: => simple2xhtml:main($tei/@id):)
};
(:~
: Assembles the intermediate format version of each notebook and copies them into one file called "fontane-full.xml".
:
: @author Michelle Weidling
: @return A string indicating the location where the full TEI/XML of the edition was stored to.
:)
declare function etTransfo:create-print-tei() as xs:string {
let $xmls := etTransfo:get-all-xmls()
let $complete-print-file :=
element {QName("http://www.tei-c.org/ns/1.0", "teiCorpus")} {
$xmls,
etTransfo:get-literature()
}
return
xmldb:store($config:data-root || "/print/xml/", "fontane-full.xml", $complete-print-file)
};
(:~
: An auxiliary function. Returns all final intermediate format TEI/XML files.
:
: @author Michelle Weidling
: @return All available final intermediate format TEI/XML files as opened documents
:)
declare function etTransfo:get-all-xmls() {
for $res in collection($config:data-root || "/print/xml/")
[contains(base-uri(.), ".xml")
and not(contains(base-uri(.), "tmp"))
and not(contains(base-uri(.), "presort"))
and not(contains(base-uri(.), "prepared"))
and not(contains(base-uri(.), "prepcom"))
and not(contains(base-uri(.), "fontane"))
and not(contains(base-uri(.), "all-headers"))
and not(contains(base-uri(.), "Kasten"))]
order by $res/tei:TEI/@key1, number($res/tei:TEI/@key2)
return
$res
};
(:~
: Creates a summary tei:div with all information needed for the print
: bibliography.
:
: @author Michelle Weidling
: @return a tei:div containing all bibliographic sections of the print
:)
declare function etTransfo:get-literature() as element(tei:div) {
element {QName("http://www.tei-c.org/ns/1.0", "text")} {
attribute type {"bibliography"},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Fontanes_Werke"},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Erstausgaben"},
etTransfo:make-bib-entries("Erstausgaben")
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Werkausgaben"},
etTransfo:make-bib-entries("Werkausgaben")
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Briefausgaben"},
etTransfo:make-bib-entries("Briefausgaben")
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Postume_Einzelausgaben"},
etTransfo:make-bib-entries("Postume_Einzelausgaben")
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Populaere_postume_Einzelausgaben"},
etTransfo:make-bib-entries("Populaere_postume_Einzelausgaben")
}
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Fontanes_Quellen"},
etTransfo:make-bib-entries("Fontanes_Quellen")
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Allgemeine_Nachschlagewerke"},
etTransfo:make-bib-entries("Allgemeine_Nachschlagewerke")
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Nachschlagewerke_der_Fontane-Forschung"},
etTransfo:make-bib-entries("Nachschlagewerke_der_Fontane-Forschung")
},
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute n {"Forschungsliteratur"},
etTransfo:make-bib-entries("Forschungsliteratur")
}
}
};
(:~
: Creates a div containing all the scholarly literature ("Forschungsliteratur")
: of a kind that's listed in the respective index. Examples for this are
: "Allgemeine Nachschlagewerke" and "Werkausgaben"
:
: @author Michelle Weidling
: @param $type The type of a tei:listBibl, e.g. "Forschungsliteratur"
: @return a tei:div containing the scribal abbreviation as well as the full
: bibliographic reference
:)
declare function etTransfo:make-bib-entries($type as xs:string) as element(tei:div)* {
for $entry in doc("/db/sade-projects/textgrid/data/xml/data/25547.xml")//tei:listBibl[@type = $type]/tei:bibl
for $choice in $entry//tei:choice
let $abbr := $choice//tei:abbr
let $full-ref := $choice//tei:expan
return
element {QName("http://www.tei-c.org/ns/1.0", "div")} {
attribute type {"entry"},
element {QName("http://www.tei-c.org/ns/1.0", "seg")} {
attribute type {"abbr"},
$abbr
},
element {QName("http://www.tei-c.org/ns/1.0", "seg")} {
attribute type {"full"},
$full-ref
}
}
};
xquery version "3.1";
(:~
: This module is responsible for retrieving all relevant information from the
: different indicies in order to create a tei:index in the simpler TEI.
:
: @author Michelle Weidling
: @version 0.1
: @since v4.0.
:)
module namespace index-info="http://fontane-nb.dariah.eu/index-info";
import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm";
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare variable $index-info:event-map :=
map:merge(for $entry in doc($config:data-root || "/data/253t0.xml")//tei:event
return
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:label[not(@type)], ", "),
"category" : string($entry/preceding::tei:head[1]),
"occs-in-nbs" : ""
}
));
declare variable $index-info:org-map :=
map:merge(for $entry in doc($config:data-root || "/data/253t1.xml")//tei:org
return
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:orgName[not(@type)], ", "),
"occs-in-nbs" : ""
}
));
declare variable $index-info:place-map :=
map:merge(for $entry in doc($config:data-root || "/data/253t2.xml")//tei:place
return
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:placeName, ", "),
"subref-of" : string-join($entry/parent::tei:place/tei:placeName, ", ")
}
));
declare variable $index-info:psn-map :=
map:merge(for $entry in doc($config:data-root ||"/data/253sx.xml")//*[self::tei:person or self::tei:personGrp]
let $same-as := $entry/ancestor::tei:listPerson//tei:person[not(@xml:id)][descendant::tei:ptr[contains(@target, $entry/@xml:id)]]/tei:persName
return
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:persName[not(@type)], ", "),
"birth" : string($entry/tei:birth),
"death" : string($entry/tei:death),
"occupation" : string($entry/tei:occupation),
"relation-to-fontane" : string($entry/tei:state/tei:desc),
"same-as" : string-join($same-as, "+")
}
));
declare variable $index-info:wrk-map :=
map:merge(
(for $entry in doc($config:data-root ||"/data/253t3.xml")//tei:item[ancestor::tei:list[@type]]
return
let $creators := $entry/tei:linkGrp/tei:link[@corresp = "http://purl.org/dc/terms/creator"]
let $creator-ids := $creators/@target/string()
let $created-by-fontane :=
if($entry/ancestor::tei:list[@type = "Fontane"]) then
true()
else
false()
let $periodical :=
if($entry/ancestor::tei:list[@type = "periodicals"]) then
true()
else
false()
let $is-periodical :=
if($periodical) then
"true"
else
"false"
return
if($creators and $periodical) then
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:name[not(@type)], ", "),
"creator-ids" : string-join($creator-ids, " "),
"periodical" : $is-periodical,
"type" : "work"
}
)
else if($creators) then
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:name[not(@type)], ", "),
"creator-ids" : string-join($creator-ids, " "),
"periodical" : $is-periodical,
"type" : "work"
}
)
else if($created-by-fontane) then
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:name[not(@type)], ", "),
"creator" : "Fontane",
"periodical" : $is-periodical,
"type" : "work"
}
)
else if($periodical) then
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:name[not(@type)], ", "),
"periodical" : $is-periodical,
"type" : "work"
}
)
else
map:entry(string($entry/@xml:id),
map {
"regular-name" : string-join($entry/tei:name[not(@type)], ", "),
"creator" : "Anonym/nicht ermittelt",
"periodical" : $is-periodical,
"type" : "work"
}
),
(: (fictional) characters mentioned/depicted in works :)
for $person in doc($config:data-root || "/data/253t3.xml")//tei:person
return
map:entry(string($person/@xml:id),
map {
"regular-name" : string-join($person/tei:persName[not(@type)], ", "),
"part-of-id" : concat("wrk:", string($person/ancestor::tei:item/@xml:id)),
"note" : string($person/tei:note[not(child::tei:ptr)]),
"type" : "person"
}
))
);
declare variable $index-info:lit-map :=
map:merge(for $entry in doc($config:data-root || "/data/25547.xml")//tei:bibl
return
map:entry(string($entry/@xml:id),
map {
"abbrev" : string-join($entry//tei:abbr, ", "),
"full-bibl" : string-join($entry//tei:expan)
}
));
(:~
: Gets information about a given term.
:
: @author Michelle Weidling
: @param $index-type the index type ("psn", "eve", ...)
: @param $term the current term, e.g. plc:Lueneburg
: @param $info the specific information to be retrieved, e.g. "regular-name"
: @return the information asked
:)
declare function index-info:get-info-about($index-type as xs:string,
$term as xs:string, $info as xs:string) as xs:string* {
local:get-main-entry($term, $index-type)
=> map:get($info)
};
(:~
: Selects the right entry on the first level of the map.
:
: @author Michelle Weidling
: @param $ref the current term, e.g. plc:Lueneburg
: @param $index-type the index type ("psn", "eve", ...)
: @return a map with all available information about the given term
:)
declare function local:get-main-entry($ref as xs:string,
$index-type as xs:string) as map()* {
let $key := substring-after($ref, ":")
return
switch ($index-type)
case "eve" return
map:get($index-info:event-map, $key)
case "org" return
map:get($index-info:org-map, $key)
case "plc" return
map:get($index-info:place-map, $key)
case "psn" return
map:get($index-info:psn-map, $key)
case "wrk" return
map:get($index-info:wrk-map, $key)
case "lit" return
map:get($index-info:lit-map, $key)
default return ()
};
xquery version "3.1";
(:~
:
: This modules serves for setting a tei:ptr right before each element that
: is referenced by an editorial commentary (tei:note[@type = 'editorial']).
:
: @author Michelle Weidling
: @version 1.0
:)
module namespace prepCom="http://fontane-nb.dariah.eu/prepCom";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare namespace xi="http://www.w3.org/2001/XInclude";
import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm";
import module namespace fontaneSimple="http://fontane-nb.dariah.eu/teisimple" at "tei2teisimple.xqm";
import module namespace functx = "http://www.functx.com";
import module namespace presort="http://fontane-nb.dariah.eu/presort" at "presort.xqm";
import module namespace simple2xhtml="http://fontane-nb.dariah.eu/simple2xhtml" at "simple2xhtml.xqm";
import module namespace tidySimple ="http://fontane-nb.dariah.eu/tidysimple" at "tidysimple.xqm";
declare variable $prepCom:literature :=
map:merge(for $entry in doc("/db/sade-projects/textgrid/data/xml/data/25547.xml")//tei:bibl
return
map:entry(string($entry/@xml:id), string($entry/tei:choice/tei:abbr[1])));
(:~
: The main function.
:
: @author Michelle Weidling
: @param $tei The current notebook in-memory
: @param $id The notebook's ID, e.g. "16b00"
: @return The current notebook with prepared editorial commentaries
:)
declare function prepCom:main($tei as node()*, $id as xs:string) {
let $add-ptr := prepCom:recursion($tei)
let $prepared := prepCom:find-literature($add-ptr)
let $store := xmldb:store($config:data-root || "/print/xml/", $id || "-prepcom.xml", $prepared)
return
$prepared
};
(:~
: This function handles the tei:ptr as well as the label creation for an
: editorial commentary. All other elements are simply copied and passed.
:
: @author Michelle Weidling
: @param $node The current node we're looking at
: @return The processed node
:)
declare function prepCom:recursion($nodes as node()*) as node()* {
for $node in $nodes return
typeswitch ($node)
case text() return
$node
case comment() return
()
(: in case of figures the text in the tei:figDesc serves as editorial
commentary - there's no tei:note referring to it. thus we set a
different tei:ptr which helps us to distinguish this case from the
regular one. :)
case element(tei:figDesc) return
(if(contains($node, "Absatzlinie")
or contains($node, "Abgrenzungslinie")
or contains($node, "Schlusslinie")) then
()
else
element {QName("http://www.tei-c.org/ns/1.0", "ptr")} {
attribute type {"editorial-commentary"},
attribute subtype {"figure"}
},
element {QName("http://www.tei-c.org/ns/1.0", name($node))} {
$node/@*,
prepCom:recursion($node/node())
})
default return
if($node/@xml:id) then
(: some notes refer to several elements because the lemma is split
into several parts. in this case we only set the ptr when we have
the first lemma part :)
(if(prepCom:check-if-first-target-of-commentary($node)) then
(element {QName("http://www.tei-c.org/ns/1.0", "ptr")} {
attribute reference {$node/@xml:id},
attribute type {"editorial-commentary"}
},
prepCom:make-complete-label($node))
else
(),
element {QName("http://www.tei-c.org/ns/1.0", name($node))} {
$node/@*,
prepCom:recursion($node/node())
})
else
element {QName("http://www.tei-c.org/ns/1.0", name($node))} {
$node/@*,
prepCom:recursion($node/node())
}
};
(:~
: In Fontane we have lots of elements that have an @xml:id. This function checks
: if this ID is the first one referred to by an editorial note. We do not
: consider other IDs in order to avoid entry duplications.
:
: @author Michelle Weidling
: @param $node the current element
: @return true() if the current element's ID is targeted by an editorial note
:)
declare function prepCom:check-if-first-target-of-commentary($node as element(*))