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

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 }"/>
......
This diff is collapsed.
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(*))
as xs:boolean {
let $note := prepCom:get-editorial-note($node)
let $corresp-ids := tokenize($note/@target, " ")
return
if(matches($corresp-ids[1], $node/@xml:id)) then
true()
else
false()
};
declare function prepCom:get-editorial-note($node as element(*))
as element(tei:note)? {
$node/ancestor::tei:TEI//tei:note[contains(@target, $node/@xml:id)]
};
(:~
: Oftentimes the label of an editorial note consists of more than one element
: which are encoded in the @target range of a tei:note. This function assembles
: all relevant labels and summarizes them in one tei:seg[@type = 'editorial-label'].
:
: @author Michelle Weidling
: @param $node The node which is the first one reference by a tei:note[@type = 'editorial'']/@target
: @return a tei:seg[@type = 'editorial-label'] with the complete label
:
: :)
declare function prepCom:make-complete-label($node as element(*))
as element(tei:seg) {
let $note := prepCom:get-editorial-note($node)
let $corresp-ids := tokenize($note/@target, " ")
return
element {QName("http://www.tei-c.org/ns/1.0", "seg")} {
attribute type {"editorial-label"},
let $no-of-elements := count($corresp-ids)
let $label-elements :=
for $id in $corresp-ids
let $id := substring-after($id, "#")
return $node/ancestor::tei:TEI//*[@xml:id = $id]
return
if($no-of-elements = 1) then
prepCom:create-label-text($label-elements)
else if($no-of-elements = 2) then
(prepCom:create-label-text($label-elements[1]),
element {QName("http://www.tei-c.org/ns/1.0", "seg")} {
attribute type {"label-separator"}
},
prepCom:create-label-text($label-elements[2]))
else if($no-of-elements gt 2) then
"MEHR ALS ZWEI TARGETS"
else
"KEIN TARGET GEFUNDEN"
}
};
(:~
: Nodes that are referenced by tei:note[@type = 'editorial']/@target can have
: lots of child nodes of which only some are text(). Since we only want the
: text itself for the label in the commentary, these text() are summarized and
: regularized.
:
: @author Michelle Weidling
: @param $node A node referred to by tei:note[@type = 'editorial']/@target
: @return The complete label text
:)
declare function prepCom:create-label-text($node as node()) as xs:string {
string-join($node/descendant::text(), " ")
=> replace("- |⸗ ", "")
};
(:~
: Finds and resolves references to (modern) scholarly literature mentioned in
: the editorial commentaries.
:
: @author Michelle Weidling
: @param The current node of a notebook
: @return The copy of a node if it's not a tei:ptr in an editorial node, else the resolved reference
:
:)
declare function prepCom:find-literature($nodes as node()*) as node()* {
for $node in $nodes return
typeswitch ($node)
case text() return
$node
case comment() return
()
case element(tei:ptr) return
if($node[ancestor::tei:note[@type = "editorial"]]) then
let $corresp-id := substring-after($node/@target, ":")
return
text {
map:get($prepCom:literature, $corresp-id),
", "
}
else
element {QName("http://www.tei-c.org/ns/1.0", name($node))} {
$node/@*,
prepCom:find-literature($node/node())
}
default return
element {QName("http://www.tei-c.org/ns/1.0", name($node))} {
$node/@*,
prepCom:find-literature($node/node())
}
};
xquery version "3.1";
module namespace presort="http://fontane-nb.dariah.eu/presort";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare namespace test="http://exist-db.org/xquery/xqsuite";
import module namespace functx="http://www.functx.com";
import module namespace simpleHelpers="http://fontane-nb.dariah.eu/teisimplehelpers" at "teisimplehelpers.xqm";
(:~
: Marks all nodes that are part of an interlinear addition.
:
: @author Michelle Weidling
: @param $node The current node
: @return The processed node
:)
declare function presort:prepare($nodes as node()*) as node()* {
for $node in $nodes
return
typeswitch ($node)
case text() return
$node
case comment() return
()
default return
if($node/preceding-sibling::*[self::tei:addSpan][1][@place = 'interlinear'][@prev or @next]
and not($node[self::tei:anchor])) then
presort:mark-interlinear-node-to-be-moved($node)
else
element {QName("http://www.tei-c.org/ns/1.0", $node/name())} {
$node/@*,
presort:prepare($node/node())
}
};
(:~
: Interlinear additions can be part of a virtual aggregation. Since their
: start is marked by tei:addSpan and their end by tei:anchor, all nodes inbetween
: have to be moved when the right chronology is established, too. To make this
: easier, the respective nodes are marked with an attribute.
:
: All other nodes are simply copied.
:
: @author Michelle Weidling
: @param $node The current node
: @return The processed node
:)
declare function presort:mark-interlinear-node-to-be-moved($node as element())
as element() {
let $addSpan := $node/preceding-sibling::*[self::tei:addSpan][1][@place = 'interlinear'][@prev or @next]
let $spanTo := substring-after($addSpan/@spanTo, "#")
let $anchor := $addSpan/following::tei:anchor[@xml:id = $spanTo]
let $nodes-inbetween := $addSpan/following-sibling::*[. << $anchor]
return
element {QName("http://www.tei-c.org/ns/1.0", $node/name())} {
$node/@*,
if(functx:is-node-in-sequence-deep-equal($node, $nodes-inbetween)) then
attribute type {"interlinear"}
else
(),
$node/node()
}
};
(:~
: Creates a new encoding structure for tei:metamark[@function = "integrate"]
: that makes further processing of them easier. All nodes relevant for the
: integration brackets are summarized in a tei:seg[@type = 'integration'].
:
: @author Michelle Weidling
: @param $node The current node
: @return The processed node
:)
declare function presort:sort-integrations($nodes as node()*) as node()* {
for $node in $nodes return
if($node/@xml:id) then
let $id := $node/@xml:id
let $metamarks := $node/ancestor::*[last()]//tei:metamark[@function = "integrate"]
let $linking-node-corresp := $metamarks[substring-after(@corresp, "#") = $id]
let $linking-node-target := $metamarks[substring-after(@target, "#") = $id]
return
if($linking-node-corresp and not($linking-node-target)) then
let $integration-target-id := replace($linking-node-corresp/@target, "#", "")
let $integration-comment := $linking-node-corresp/ancestor::*[last()]//*[@xml:id = $integration-target-id]
return
element {QName("http://www.tei-c.org/ns/1.0", "seg")} {
attribute type {"integration"},
$integration-comment,
$linking-node-corresp,
presort:keep-node-integrations($node)
}
else if($linking-node-target) then
()
else
presort:keep-node-integrations($node)
else if($node[self::tei:metamark[@function = "integrate"]]) then
()
else if($node[self::text() or self::comment()]) then
$node
else
presort:keep-node-integrations($node)
};
(:~
: An auxiliary function that copies a given node while sorting the integrations.
:
: @author Michelle Weidling
: @param $node The current node
: @return A copy of the given node
:)
declare function presort:keep-node-integrations($node as node()) as node()* {
element {QName("http://www.tei-c.org/ns/1.0", $node/name())} {
$node/@*,
(: $node/(@* except (@prev, @next)), (: attrs only visible for debugging :):)
presort:sort-integrations($node/node())
}
};
xquery version "3.1";
(:~
: This modules runs the first and second process that transforms the Fontane
: TEI subset into a simpler TEI encoding.
:
: @author Michelle Weidling
: @version 1.0
:)
declare namespace tei="http://www.tei-c.org/ns/1.0";
import module namespace etTransfo="http://fontane-nb.dariah.eu/etTransfo" at "etTransfo.xqm";
declare option exist:serialize "method=xml media-type=text/xml expand-xincludes=no";
etTransfo:complete()
This diff is collapsed.
xquery version "3.1";
(:~
: This module is a refactored version of the old presort module which lead to
: unidentifiable errors while transforming the original encoding to another TEI.
:
: It mainly deals with bringing everything into the right order, i.e. in a fully
: legible flow of text that has the right chronological flow.
:
:)
module namespace fsort="http://fontane-nb.dariah.eu/sort";
declare namespace tei="http://www.tei-c.org/ns/1.0";
import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm";
import module namespace presort="http://fontane-nb.dariah.eu/presort" at "presort.xqm";
(:~
: The main function. Sorts each notebook and saves a sorted version at
: /db/sade-projects/textgrid/data/xml/print/xml/notebook_uri-presort.xml.
:
: @author Michelle Weidling
:)
declare function fsort:main($tei as node()*) as element(tei:TEI) {
let $prepared := presort:prepare($tei)
let $tei := fsort:sort($prepared)
let $fully-sorted := presort:sort-integrations($tei)
let $id := $tei/@id
let $store := xmldb:store($config:data-root || "/print/xml/", $id || "-presort.xml", $fully-sorted)
return $fully-sorted
};
(:~
: The main sorting routine. Everything apart from tei:hi and tei:rs follows the
: same rules that are specified in fsort:default-return().
:
:)
declare function fsort:sort($nodes as node()*) {
for $node in $nodes return
typeswitch ( $node )
case text() return
$node