diff --git a/modules/fontane/edited-text/abbrev-index.xqm b/modules/fontane/edited-text/abbrev-index.xqm index 9f8e079b2a432c018dd8f835cf747f893b91f257..40e7cbfec4614911cb22d94cf7d8a8f18b3e965b 100644 --- a/modules/fontane/edited-text/abbrev-index.xqm +++ b/modules/fontane/edited-text/abbrev-index.xqm @@ -3,7 +3,7 @@ xquery version "3.1"; (:~ : This module is responsible for getting an XML version of the abbreviations : index which can be converted to TeX. This XML version is appended to - : fontane-full.xml during the creation of the intermediate format in etTransfo.xmq. + : fontane-full.xml during the creation of the intermediate format in etTransfo.xqm. : : @author Michelle Weidling : @version 0.1 @@ -25,6 +25,7 @@ declare function abbrev-index:main() as element(tei:div) { let $transformed := abbrev-index:transform($file) => abbrev-index:tidy() + => abbrev-index:sort() return element tei:div { @@ -132,3 +133,51 @@ declare function abbrev-index:tidy($nodes as node()*) as node()* { else () }; + + +declare function abbrev-index:sort($nodes as node()*) as node()* { + for $node in $nodes return + typeswitch ($node) + + case text() return + $node + + case element(tei:row) return + let $first-char := + normalize-space($node/tei:cell[1]/text()) + => substring(1, 1) + => upper-case() + let $prev-first-char := + normalize-space($node/preceding-sibling::tei:row[1]/tei:cell[1]/text()) + => substring(1, 1) + => upper-case() + let $current-row := + element {QName("http://www.tei-c.org/ns/1.0", $node/local-name())} { + $node/@*, + abbrev-index:sort($node/node()) + } + return + if($node[@role = "head"]) then + $current-row + else if(not($first-char = $prev-first-char) + or not($node/preceding-sibling::tei:row[1]) + or $node/preceding-sibling::tei:row[1][@role = "head"]) then + ( + element {QName("http://www.tei-c.org/ns/1.0", $node/local-name())} { + element tei:cell { + attribute type {"lemma"}, + $first-char + }, + element tei:cell {} + }, + $current-row + ) + else + $current-row + + default return + element {QName("http://www.tei-c.org/ns/1.0", $node/local-name())} { + $node/@*, + abbrev-index:sort($node/node()) + } +}; diff --git a/modules/fontane/edited-text/etTransfo.xqm b/modules/fontane/edited-text/etTransfo.xqm index 75aa02bf51aeb824c0f5e1fc562054080d201f8e..1a297dd90dd23e626c8104d563acbdf5d1b1c333 100644 --- a/modules/fontane/edited-text/etTransfo.xqm +++ b/modules/fontane/edited-text/etTransfo.xqm @@ -22,9 +22,7 @@ import module namespace config="http://textgrid.de/ns/SADE/config" at "../../con 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 macro-sort="http://fontane-nb.dariah.eu/macro-sort" at "macro-sort.xqm"; 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"; @@ -192,18 +190,9 @@ declare function etTransfo:create-htmls($showcase as xs:string) as xs:string* { : @param $tei The current notebook as element(tei:TEI) :) declare function etTransfo:transform-tei($tei as element(tei:TEI), $log as xs:string) { -(: macro-sort:main($tei, $tei/@id):) -(: let $macro-sorted :=:) -(: try {:) -(: macro-sort:main($tei, $tei/@id):) -(: } catch * {:) -(: etTransfo:add-log-entry($log, "ETTRANSFO14: Error while macro sorting this notebook. Reason: " ||:) -(: concat("[", $err:line-number, ": ", $err:column-number, "] Error ", $err:code, ": ", $err:description)):) -(: }:) let $sorted := try { fsort:main($tei, $log) -(: fsort:main($macro-sorted, $log) :) } catch * { etTransfo:add-log-entry($log, "ETTRANSFO09: Error while sorting this notebook. Reason: " || concat("[", $err:line-number, ": ", $err:column-number, "] Error ", $err:code, ": ", $err:description)) @@ -266,6 +255,12 @@ declare function etTransfo:create-print-tei() as xs:string { abbrev-index:main() } catch * { etTransfo:add-log-entry($log, "ETTRANSFO07: An error occured while creating the index of abbreviations.") + }, + + try { + etTransfo:create-overall-toc() + } catch * { + etTransfo:add-log-entry($log, "ETTRANSFO10: An error occured while creating the overall TOC..") } } return @@ -484,3 +479,48 @@ declare function etTransfo:report-errors() as item()* { util:log-system-out("Total: " || count(xmldb:get-child-resources($log-path)) || " notebook(s).") ) }; + + +(:~ + : creates the overall TOC by collection information from all Überblickskommentare. + : this info is needed for a separate kind of index in the book. + : + : TODO: fine tuning + : + : @author Michelle Weidling:) +declare function etTransfo:create-overall-toc() as element(tei:div) { + let $nbs := collection($config:data-root || "/data") + let $items := collection($config:data-root || "/data")//tei:TEI[descendant::tei:title = "Notizbuch E1"]/tei:teiHeader//tei:msContents/tei:ab/tei:list[@type="editorial"]/tei:item + let $sortPattern := "^\W+" + + return element tei:div { + attribute type {"overall-toc"}, + let $segs := + for $doc in $nbs + return + let $nb-name := $doc//tei:fileDesc/tei:titleStmt/tei:title[1]/substring-after(., " ") + return + for $item in $doc//tei:msContents/tei:ab/tei:list[@type="editorial"]//tei:item return + let $first-ref := $item//tei:ref[@type = "first"]/@target/string() + let $last-ref := $item//tei:ref[@type = "last"]/@target/string() + let $refs := + for $ref in ($first-ref, $last-ref) return + let $tokens := tokenize($ref, " ") + return $tokens[2] + return + element tei:seg { + attribute type {$nb-name}, + attribute source { + let $string := for $ref in $refs return + substring-after($ref, "@xml:id='") + => substring-before("']") + return + string-join($string, " ") + }, + normalize-space(functx:substring-before-last($item, ")") || ")") + } + return for $seg in $segs + order by replace($seg, $sortPattern, "") => substring(1, 1) => upper-case() + return $seg + } +}; diff --git a/modules/fontane/edited-text/macro-sort.xqm b/modules/fontane/edited-text/macro-sort.xqm deleted file mode 100644 index a9436f775c845b181171d1f6a96fe6c10e0130a3..0000000000000000000000000000000000000000 --- a/modules/fontane/edited-text/macro-sort.xqm +++ /dev/null @@ -1,100 +0,0 @@ -xquery version "3.1"; - -module namespace macro-sort="http://fontane-nb.dariah.eu/macro-sort"; - -import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm"; - -declare namespace tei="http://www.tei-c.org/ns/1.0"; -declare namespace xi="http://www.w3.org/2001/XInclude"; - - - -declare function macro-sort:main($tei as node()*, $uri as xs:string) as node()* { - let $header := $tei//tei:teiHeader - let $sorted := macro-sort:sort($tei//tei:sourceDoc) -(: let $cleared := macro-sort:clear($sorted):) - let $cleared := $sorted - - let $final-tei := - element tei:TEI { - $header, - $cleared - } - - let $store := xmldb:store($config:data-root || "/print/xml/", $uri || "-macrosort.xml", $final-tei) - - return - $final-tei - }; - - declare function macro-sort:sort($nodes as node()*) as node()* { - for $node in $nodes return - typeswitch ($node) - - case text() return - $node - - case comment() return - $node - - case element(tei:milestone) return - if($node/@unit = "section") then - let $end-point-id := replace($node/@spanTo, "#", "") - let $end-point := $node/root()//tei:anchor[@xml:id = $end-point-id] - let $number := substring-after($node/@type, "Text_") - let $handshift := $node/preceding::tei:milestone[@unit = "handshift"][1] - - return - element tei:div { - attribute n {$number}, -(: $node/(@* except @spanTo),:) - $node/@*, - $handshift, - (: all nodes on the current surface :) - $node/following-sibling::node()[. << $end-point], - $node/../following-sibling::node()[. << $end-point], - (: all complete surfaces before the anchor :) - $node/ancestor::tei:surface/following-sibling::tei:surface[. << $end-point], - (: all elements on the surface that contains the anchor which are before the anchor :) - $node/ancestor::tei:surface/following-sibling::tei:surface[descendant::tei:anchor[@xml:id = $end-point-id]]//tei:anchor[@xml:id = $end-point-id]/preceding-sibling::* - } - - else - macro-sort:copy-element($node) - - default return - let $section-marker := $node/preceding::tei:milestone[@unit = "section"][1] - let $end-point-id := replace($section-marker/@spanTo, "#", "") - let $end-point := $node/root()//tei:anchor[@xml:id = $end-point-id] - - return - if($node[. >> $section-marker and . << $end-point]) then - () - else - macro-sort:copy-element($node) - }; - - -declare function macro-sort:copy-element($node as element(*)) as element(*) { - element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { - $node/@*, - macro-sort:sort($node/node()) - } -}; - -declare function macro-sort:clear($nodes as node()*) as node()* { - for $node in $nodes return - typeswitch ($node) - - case text() return - $node - - case comment() return - $node - - default return - if($node/@outside-section = "true") then - () - else - $node -}; diff --git a/modules/fontane/edited-text/prepcom.xqm b/modules/fontane/edited-text/prepcom.xqm index 033f2581d1cbfa77a377f6ff05d1b803ba012b14..c42b2a6b04c87baaa7604a78ce6ff5d39413f284 100644 --- a/modules/fontane/edited-text/prepcom.xqm +++ b/modules/fontane/edited-text/prepcom.xqm @@ -6,20 +6,15 @@ xquery version "3.1"; : is referenced by an editorial commentary (tei:note[@type = 'editorial']). : : @author Michelle Weidling - : @version 1.0 + : @version 1.1 :) 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 @@ -35,7 +30,8 @@ declare variable $prepCom:literature := : @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) { +declare function prepCom:main($tei as node()*, $id as xs:string) +as element(tei:TEI){ 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) @@ -158,7 +154,7 @@ as element(tei:seg) { let $label-elements := for $id in $corresp-ids let $id := substring-after($id, "#") - return $node/ancestor::tei:TEI//*[@xml:id = $id] + return $node/root()//*[@xml:id = $id] return if($no-of-elements = 1) then prepCom:create-label-text($label-elements) @@ -188,7 +184,7 @@ as element(tei:seg) { : @return The complete label text :) declare function prepCom:create-label-text($node as node()) as xs:string { - string-join($node/descendant::text(), " ") + string-join($node/descendant::text()[not(parent::tei:expan)], "") => replace("- |⸗ ", "") }; diff --git a/modules/fontane/edited-text/presort.xqm b/modules/fontane/edited-text/presort.xqm deleted file mode 100644 index 06e0b832187d4dee1d626fa31061f2328f541865..0000000000000000000000000000000000000000 --- a/modules/fontane/edited-text/presort.xqm +++ /dev/null @@ -1,131 +0,0 @@ -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 - if(matches($node/string(), "rotate")) then - $node - else - () - - 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 tei: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()) - } -}; diff --git a/modules/fontane/edited-text/simple2xhtml.xqm b/modules/fontane/edited-text/simple2xhtml.xqm index 94caf26780729abc387f9d4509e9b81da91b3894..78444415fcd6ee8e3330c6ee418a8428afa4566f 100644 --- a/modules/fontane/edited-text/simple2xhtml.xqm +++ b/modules/fontane/edited-text/simple2xhtml.xqm @@ -14,28 +14,44 @@ declare namespace tei="http://www.tei-c.org/ns/1.0"; declare namespace xhtml="http://www.w3.org/1999/xhtml"; import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm"; +import module namespace functx="http://www.functx.com"; declare function simple2xhtml:main($nodes as node()*, $uri as xs:string) { let $xhtml := element xhtml:div {simple2xhtml:recursion($nodes//tei:text)} let $tidy := element xhtml:div {simple2xhtml:tidy($xhtml)} - let $store := xmldb:store($config:data-root || "/print/xhtml/", $uri || ".html", $tidy) return - $tidy + xmldb:store($config:data-root || "/print/xhtml/", $uri || ".html", $tidy) }; (:~ : Tidy up all that messy white spaces. - : @TODO further optimization of tei2simple :) -declare function simple2xhtml:fix-whitespaces($nodes as node()*) as node()* { - let $string := - serialize($nodes) -(: => replace("[\t\n]", ""):) -(: => replace("[\s]+", " "):) -(: => replace(" ,", ","):) -(: => replace(" \.", "."):) - - return $string +declare function simple2xhtml:fix-whitespaces($node as xs:string) as xs:string { + let $general := + replace($node, " ,", ",") + => replace("\?@\?", " ") + => replace("\?@@\?", "〃") + => replace(" \?", "?") + => replace(" \.", ".") + => replace(" ;", ";") + => replace("@@", " ") + => replace("  ", " ") + => replace(":", ": ") + => replace("\s+“", "“") +(: let $general :=:) +(: if(normalize-space($node) = "":) +(: and matches(substring($node/following::text()[1], 1, 1), "[,\.“\-\)]")) then:) +(: ():) +(: else:) +(: $node:) + let $hyphen := + if(matches($general, "@P[A-Z]")) then + replace($general, "@P", "-") + => replace("@", "") + else + replace($general, "@P", "") + => replace("@", "") + return $hyphen }; @@ -55,27 +71,43 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { if (normalize-space($node) = "") then () else - element xhtml:span { - simple2xhtml:set-hs-info($node, ()), - replace($node, " ,", ",") - => replace(" \?", "?") - => replace(" \.", ".") - => replace(" ;", ";") - => replace("@@", " ") - => replace("@P", "") - => replace("  ", " ") - => replace(":", ": ") - => replace(" “", "“") - } + ( + if($node/preceding-sibling::*[1][self::tei:milestone[@rendition = "indent"]]) then + element xhtml:br {} + else + (), + element xhtml:span { + simple2xhtml:set-hs-info($node, "text"), + if($node/preceding-sibling::*[1][self::tei:milestone[@rendition = "indent"]]) then + attribute style {"margin-left: 20px;"} + else if($node/preceding-sibling::*[1][self::tei:milestone[@rendition = "align(center)"]]) then + attribute style {"text-align: center;"} + else + (), + simple2xhtml:fix-whitespaces($node) + } + ) case element(tei:body) return - element xhtml:div { - simple2xhtml:set-hs-info($node, ()), - simple2xhtml:recursion($node/node()) - } + ( + element xhtml:div { + simple2xhtml:set-hs-info($node, ()), + simple2xhtml:recursion($node/node()) + }, + for $note in $node/root()//tei:note[@type = "authorial" and @subtype ="footnote"] return + element xhtml:div { + attribute id {$note/../@xml:id}, + attribute class {"nb-footnote"}, + simple2xhtml:recursion($note/node()) + } + ) case element(tei:abbr) return - (text{" "}, + ( + if($node/@prev) then + () + else + text{" "}, element xhtml:span { simple2xhtml:set-hs-info($node, "abbr"), simple2xhtml:recursion($node/node()) @@ -125,13 +157,40 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { simple2xhtml:recursion($node/node()) } else + (if($node/@type = "marked_off") then + element xhtml:div { + attribute class {"nb-editorial"}, + text{""} + } + else if($node/@type = "multiphrase") then + element xhtml:div { + attribute class {"nb-editorial"}, + text{""} + } + else + (), element xhtml:div { - if($node/@type = "label") then - simple2xhtml:set-hs-info($node, "nb-label") + if($node/@type = ("label", "additional", "marked_off", "indent")) then + simple2xhtml:set-hs-info($node, "nb-" || $node/@type) + else simple2xhtml:set-hs-info($node, ()), simple2xhtml:recursion($node/node()) - } + + }, + if($node/@type = "marked_off") then + element xhtml:div { + attribute class {"nb-editorial"}, + text{""} + } + else if($node/@type = "multiphrase") then + element xhtml:div { + attribute class {"nb-editorial"}, + text{""} + } + else + () + ) case element(tei:expan) return element xhtml:span { @@ -146,33 +205,40 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { } case element(tei:hi) return - (text{" "}, - element xhtml:span { - simple2xhtml:set-hs-info($node, "nb-underline"), - simple2xhtml:recursion($node/node()) - }) + if($node/ancestor::tei:seg[@type = ("reduplication", "missing-syllable", "missing-hyphen", "supplied")] + or $node[@type = "blue-underlined"]) then + element xhtml:span { + simple2xhtml:set-hs-info($node, "nb-" || $node/@type), + simple2xhtml:recursion($node/node()) + } + + else if($node/@type = "vertical-mark") then + element xhtml:span { + simple2xhtml:set-hs-info($node, "nb-" || $node/@type), + simple2xhtml:recursion($node/node()) + } + + else + element xhtml:span { + simple2xhtml:set-hs-info($node, "nb-underline"), + simple2xhtml:recursion($node/node()) + } case element(tei:lb) return if ($node/@type="edited_text") then element xhtml:br {} + else if ($node/@type="keepIndent") then + element xhtml:div { + attribute class {"nb-keepIndent"} + } else () case element(tei:list) return - (: this matches the FIRST element of the virtual aggregation :) - if($node/@next and not($node/@prev)) then - element xhtml:ul { - attribute class {"nb-list"}, - simple2xhtml:apply-next-element($node) - } - (: this matches all OTHER elements of the virtual aggregation :) - else if($node/@prev or $node/@next) then - () - else - element xhtml:ul { - attribute class {"nb-list"}, - simple2xhtml:recursion($node/node()) - } + element xhtml:ul { + attribute class {"nb-list"}, + simple2xhtml:recursion($node/node()) + } case element(tei:item) return element xhtml:li { @@ -241,10 +307,16 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { } case element(tei:milestone) return - if($node/@unit = "line") then + if($node/@unit = "line" + and ($node/ancestor::tei:seg[@type = "said"][not(preceding-sibling::*[1][self::*[@type = "said"]] or preceding-sibling::*[1]//*[last()][self::*[@type = "said"]])] + or $node/ancestor::tei:div[@type = "edited_text"])) then + element xhtml:br {} + + else if($node/@unit = "line") then let $next-char := substring($node/following::text()[1], 1, 1) + let $prev-char := substring($node/preceding::text()[1], 1, 1) return - if(matches($next-char, "[\.\)\?,;!]") + if((matches($next-char, "[\.\)\?,;!]") or $next-char = "“") and not(ends-with($node/preceding::text()[1], "@P"))) then () @@ -252,9 +324,15 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { or ends-with($node/preceding::text()[1], "-")) then () + else if(matches($prev-char, "\(")) then + () + else if($node/preceding-sibling::*[1][self::tei:rs[concat('#', @xml:id) = $node/following-sibling::*[2][self::tei:rs]/@prev]]) then () + else if($node/preceding-sibling::*[1][self::tei:abbr[@next]]) then + () + else text{" "} @@ -280,75 +358,189 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { () - (: lines are handled together with tei:milestone[@unit = "start-lg"]. all - other verses are ignored. :) case element(tei:l) return - () + (element xhtml:div { + attribute class {"nb-verse"}, + simple2xhtml:recursion($node/node()) + }, + if($node/following-sibling::*[1][not(self::tei:seg[@type = "verse"] or self::tei:l)]) then + element xhtml:span { + attribute class {"nb-verses-end"} + } + else + () + ) case element(tei:ab) return if($node/@type = "sketch" and $node/descendant::tei:figure) then - element xhtml:table { - attribute class {"nb-sketch"}, - element xhtml:tr { - simple2xhtml:recursion($node/node()) + ( + if($node//tei:ptr[@type = "editorial-commentary"]) then + simple2xhtml:recursion($node//tei:ptr[@type = "editorial-commentary"]) + else + (), + element xhtml:table { + attribute class {"nb-sketch"}, + element xhtml:tr { + simple2xhtml:recursion($node/node()) + } } + ) + + else if($node/@type = "footnote-mark") then + element xhtml:seg { + attribute class {"nb-" || $node/@type}, + simple2xhtml:recursion($node/node()) } - else if($node/@type = ("caret")) then + else if($node/@type = "caret") then () - else if($node/@type = "footnote-mark") then + else if($node/@type = "verse_marker") then element xhtml:seg { attribute class {"nb-" || $node/@type}, - simple2xhtml:recursion($node/node()) + if($node/@rend = "pipe") then + text{"|"} + else + text{"/"} } - else if($node/@type = "short-paragraph-line") then + else if($node/@type = ("short-paragraph-line", "sum", "double-sum", + "difference", "long-end-line", "end-line", "short-paragraph-line-double", + "footnotes")) then element xhtml:div { attribute class {$node/@type} } - else if($node/@type = "paragraph" and $node/string = "z") then - (element xhtml:br {}, + else if($node/@type = "bottom-brace") then + (
, + element xhtml:span { + attribute class {$node/@type}, + text{"⏟"} + }, +
) + + else if($node/@type = "paragraph") then element xhtml:div { - attribute class {"nb-paragraph"} - }) + attribute class {"nb-paragraph-line-special-characters"}, + if($node/string() = "z") then + () + else + simple2xhtml:recursion($node/node()) + } + + else if($node/@type = "authorial_note") then + text{"authorial note"} else simple2xhtml:recursion($node/node()) case element(tei:figure) return - let $captions-before := - $node/preceding-sibling::tei:seg[@type = "caption"][ancestor::tei:ab = $node/ancestor::tei:ab] - let $captions-after := - $node/following-sibling::tei:seg[@type = "caption"][ancestor::tei:ab = $node/ancestor::tei:ab] - return - (: make captions left of sketch:) - (if(exists($captions-before)) then - simple2xhtml:make-img-captions($captions-before, "right-aligned") - else - (), + if($node/ancestor::tei:div/@type = "genealogy") then + let $coordinates := tokenize( $node/ancestor::tei:div[1]/@points, " ") + return + ( + {$node/@xml:id ! attribute id { string(.) }, + for $pair in 1 to (count($coordinates) - 1) + let $x1 := tokenize($coordinates[$pair], ',')[1] + let $y1 := tokenize($coordinates[$pair], ',')[2] + let $x2 := tokenize($coordinates[$pair + 1], ',')[1] + let $y2 := tokenize($coordinates[$pair + 1], ',')[2] + return + + } + , + element xhtml:div { + attribute class {'hrHover'}, + tokenize($node//tei:figDesc/tei:ref/text(), ' ')[2] => replace(";", "") + } + ) - element xhtml:td { - attribute class {"nb-img"}, - if($node/@rotate) then - attribute style {concat("width: ", $node/parent::*/@height, "; height: ", $node/parent::*/@width, ";")} + else if(not($node/ancestor::tei:ab/preceding-sibling::*[1][descendant::tei:figure[@type = "double"]])) then + let $captions-before := + $node/preceding-sibling::tei:seg[@type = "caption"][ancestor::tei:ab = $node/ancestor::tei:ab] + let $captions-after := + $node/following-sibling::tei:seg[@type = "caption"][ancestor::tei:ab = $node/ancestor::tei:ab] + return + (: make captions left of sketch:) + (if(exists($captions-before)) then + simple2xhtml:make-img-captions($captions-before, "right-aligned") else (), - simple2xhtml:make-img($node, "block") - }, - (: make captions right of sketch:) - if(exists($captions-after)) then - simple2xhtml:make-img-captions($captions-after, "left-aligned") + (: for an ordinary img or the left part of a double img :) + element xhtml:td { + if($node/@type = "double") then + attribute class {"nb-double-img"} + else + attribute class {"nb-img"}, + (: in case of a 180deg rotation the original width/height + preserved while we have to switch width and height in + case of 90deg/270deg :) + if($node/@rotate = "180") then + attribute style {concat("width: ", $node/parent::*/@width, "; height: ", $node/parent::*/@height, ";")} + else if($node/@rotate) then + attribute style {concat("width: ", $node/parent::*/@height, "; height: ", $node/parent::*/@width, ";")} + else + (), + if($node/@type = "double") then + simple2xhtml:make-img($node, "double") + else + simple2xhtml:make-img($node, "block") + }, + + if($node/@type = "double" + and $node/ancestor::tei:ab/following-sibling::*[1][descendant::tei:figure[@type = "double"]]) then + let $next-node := $node/ancestor::tei:ab/following-sibling::*[1]/descendant::tei:figure[@type = "double"] + return + element xhtml:td { + attribute class {"nb-double-img"}, + if($next-node/@rotate) then + attribute style {concat("width: ", $next-node/parent::*/@height, "; height: ", $next-node/parent::*/@width, ";")} + else + (), + simple2xhtml:make-img($next-node, "double") + } + + else + (), + + (: make captions right of sketch:) + if(exists($captions-after)) then + simple2xhtml:make-img-captions($captions-after, "left-aligned") + else + ()) + + (: right parts of sketches on double pages are processed when processing the left part :) else - ()) + () case element(tei:seg) return if($node/@type = ("caption", "editorial-label", "multiphrase")) then () + else if($node/@type = "verse") then + (element xhtml:div { + attribute class {"nb-verse"}, + simple2xhtml:recursion($node/node()) + }, + if($node/following-sibling::*[1][not(self::tei:seg[@type = "verse"] or self::tei:l)]) then + element xhtml:span { + attribute class {"nb-verses-end"} + } + else + () + ) + + else if($node/@type = "framed") then + element xhtmlspan { + simple2xhtml:set-hs-info($node, "nb-framed"), + simple2xhtml:recursion($node/node()) + } + else if($node[@rendition = ("vertical-align:super", "vertical-align:sub") and (following-sibling::*[1][self::tei:g[@ref ="#hb"]] @@ -359,18 +551,62 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { else if($node/@type = "integration") then simple2xhtml:make-integration($node) - else + else if($node/@type = ("missing-hyphen", "supplied", "blue-underlined", "highlighted-area")) then + element xhtml:span { + simple2xhtml:set-hs-info($node, "nb-" || $node/@type), + simple2xhtml:recursion($node/node()) + } + + else if($node/@type = "said") then + element xhtml:div { + attribute class {"nb-said"}, + simple2xhtml:recursion($node/node()) + } + + else if(matches($node/@rendition, "smallcaps")) then + element xhtml:span { + simple2xhtml:set-hs-info($node, "nb-smallcaps"), + attribute style {$node/@rendition}, + simple2xhtml:recursion($node/node()) + } + + else if($node/@type = "initials") then element xhtml:span { - simple2xhtml:set-hs-info($node, "nb-seg"), -(: attribute style {$node/@rendition},:) + simple2xhtml:set-hs-info($node, "nb-initials"), + attribute style {$node/@rendition}, simple2xhtml:recursion($node/node()) } + else + ( + element xhtml:span { + simple2xhtml:set-hs-info($node, "nb-seg"), + attribute style {$node/@rendition}, + simple2xhtml:recursion($node/node()) + }, + if(matches($node/@rendition, "letter\-spacing") + and not(ends-with($node, "-"))) then + let $next-char := substring($node/following::text()[1], 1, 1) + return if(matches($next-char, "\.,\)")) then + () + else + text{" "} + else + (), + if($node/ancestor::*[@type ="said"]) then + element xhtml:br {} + else + () + ) + case element(tei:unclear) return - element xhtml:span { - attribute class {"unclear"}, - simple2xhtml:recursion($node/node()) - } + ( + element xhtml:span { + attribute class {"unclear"}, + simple2xhtml:recursion($node/node()) + }, + text{" "} + ) case element(tei:date) return (simple2xhtml:set-whitespace-before($node), @@ -386,14 +622,17 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { () case element(tei:note) return - if($node/@type = "editorial") then + if($node/@type = ("editorial") + and not($node/@subtype = "footnote")) then element xhtml:span { - attribute class {"editorial-note"}, + attribute class {$node/@type || "-note"}, simple2xhtml:recursion($node/node()) } - else if($node/@subtype = "footnote") then + else if($node/@type = "authorial") then + simple2xhtml:make-modal($node) + else if($node/@subtype = ("revision")) then element xhtml:div { - attribute class {"nb-footnote"}, + attribute class {"nb-" || $node/@subtype}, simple2xhtml:recursion($node/node()) } else @@ -438,6 +677,115 @@ declare function simple2xhtml:recursion($nodes as node()*) as node()* { else () + case element(tei:table) return + (element xhtml:table { + attribute class {"nb-computation-table"}, + simple2xhtml:recursion($node/tei:row) + }, + simple2xhtml:recursion($node/node()[not(ancestor-or-self::tei:row)])) + + case element(tei:row) return + element xhtml:tr { + simple2xhtml:recursion($node/node()) + } + + case element(tei:cell) return + element xhtml:td { + simple2xhtml:recursion($node/node()) + } + + case element(tei:gap) return + if($node/following-sibling::*[1][self::tei:seg[@type = "supplied"]]) then + () + else + element xhtml:span { + if($node/@unit = "mm") then + attribute class {"gap-" || $node/@quantity} + else + attribute class {"gap"}, + switch ($node/@unit) + case "words" return + text{"X---x"} + case "cap_words" return + text{"X---x"} + case "uncap_words" return + text{"x---x"} + case "cap_word_chars" return + text{"X---x"} + case "uncap_word_chars" return + text{"x---x"} + case "lc_chars" return + text{ + for $iii in 1 to $node/@quantity return + "x" + } + case "uc_chars" return + text{ + for $iii in 1 to $node/@quantity return + "X" + } + case "chars" return + text{ + for $iii in 1 to $node/@quantity return + "X" + } + default return () + } + + case element(tei:space) return + if($node/@type = ("pause", "placeholder")) then + element xhtml:span { + attribute class {"nb-" || $node/@type} + } + else + () + + case element(tei:ref) return + if($node/tei:ab[@type = "footnote-mark"]) then + let $target-id := replace($node/@target, "#", "") + let $target := $node/root()//*[@xml:id = $target-id] + + return + element xhtml:a { + attribute href {$node/@target}, + simple2xhtml:recursion($node/tei:ab) + } + else + simple2xhtml:recursion($node/node()) + + case element(tei:choice) return + if($node/tei:expan) then + element xhtml:span { + attribute class {"choice"}, + element xhtml:div { + attribute class {"expan italic"}, + simple2xhtml:recursion($node/tei:expan/node()) + }, + simple2xhtml:recursion($node/tei:abbr), + let $next-char := substring($node/following::text()[1], 1, 1) + return if(matches($next-char, "\.,\)")) then + () + else + text{" "} + } + else + simple2xhtml:recursion($node/node()) + + case element(tei:abbr) return + element xhtml:span { + attribute id {$node/@xml:id}, + attribute class {"abbr"}, + simple2xhtml:recursion($node/node()) + } + + case element(tei:expan) return + () + + case element(tei:ptr) return + if($node[@type = "editorial-commentary"]) then + simple2xhtml:make-modal($node) + else + () default return simple2xhtml:recursion($node/node()) @@ -488,11 +836,15 @@ $mode as xs:string) as element(xhtml:img) { return element xhtml:img { + if($node/@id) then + attribute id {$node/@id} + else + (), attribute src {$node/@href}, - attribute alt {$node//tei:figDesc/string()}, -(: if($mode = "block") then:) -(: attribute class {"nb-block-img"}:) -(: else:) + attribute alt {$node//tei:figDesc/string() => replace("@@", " ")}, + if($mode = "double") then + attribute class {"nb-double-img"} + else attribute class {"nb-block-img"}, attribute style {$width || $height || $rotation} } @@ -606,12 +958,25 @@ as attribute() { }; +(:~ + : Handles the creation of an integration, i.e. authorial comments to some part + : of a text. An integration is rendered as a table with 3 columns in which the + : middle part contains the bracket and the outer ones the text referred to resp. + : the comment if the bracket faces left or right. + : In some cases we have horizontal brackets which we render as a table with + : 3 rows. + : + : @author Michelle Weidling + :) declare function simple2xhtml:make-integration($node as element(tei:seg)) { - let $bracket := $node//tei:ab[@function = "integrate"] - - (: target is the side where the pointy end of the bracket goes. - corresp is the side where bracket faces to. - example: target { corresp :) + let $bracket := $node//tei:ab[@function = ("integrate", "authorial_note")][1] + let $orientation := substring-after($bracket/@rend, "bracket_") + + (: + target is the side where the pointy end of the bracket goes. + corresp is the side where bracket faces to. + example: target { corresp + :) let $target-id := replace($bracket/@target, "#", "") let $target := $node//*[@xml:id = $target-id] let $corresp-id := replace($bracket/@corresp, "#", "") @@ -626,44 +991,92 @@ declare function simple2xhtml:make-integration($node as element(tei:seg)) { $lines-corresp let $bracket-size := 12 * ($max-number-of-lines + 1) - return - element xhtml:table { - attribute class {"integration"}, - element xhtml:tr { - element xhtml:td { - attribute class {"integration-left"}, - if($bracket/@rend = "bracket_right") then - simple2xhtml:recursion($corresp/node()) - else if($bracket/@rend = "bracket_left") then - simple2xhtml:recursion($target/node()) - else - () - }, - element xhtml:td { - attribute class {"integration-bracket"}, - attribute style {"font-size: " || $bracket-size || "pt;"}, - if($bracket/@rend = "bracket_right") then - text{"}"} - else if($bracket/@rend = "bracket_left") then - text{"{"} - else - () - }, - element xhtml:td { - attribute class {"integration-right"}, - if($bracket/@rend = "bracket_right") then - simple2xhtml:recursion($target/node()) - else if($bracket/@rend = "bracket_left") then - simple2xhtml:recursion($corresp/node()) - else - () - } + if($orientation = "bottom") then + simple2xhtml:make-bottom-bracket-integration-table($corresp, $target) + else + simple2xhtml:make-lr-bracket-integration-table($orientation, $corresp, $target, $bracket-size) + + + +}; + + +(:~ + : Renders the table for integrations with left or right facing brackets. + : + : @author Michelle Weidling + :) +declare function simple2xhtml:make-lr-bracket-integration-table($orientation as xs:string, +$corresp as node()*, $target as node()*, $bracket-size as xs:integer) { + element xhtml:table { + attribute class {"integration"}, + element xhtml:tr { + element xhtml:td { + attribute class {"integration-left"}, + if($orientation = "right") then + simple2xhtml:recursion($corresp/node()) + else if($orientation = "left") then + simple2xhtml:recursion($target/node()) + else + () + }, + element xhtml:td { + attribute class {"integration-bracket"}, + attribute style {"font-size: " || $bracket-size || "pt;"}, + if($orientation = "right") then + text{"}"} + else if($orientation = "left") then + text{"{"} + else + () + }, + element xhtml:td { + attribute class {"integration-right"}, + if($orientation = "right") then + simple2xhtml:recursion($target/node()) + else if($orientation = "left") then + simple2xhtml:recursion($corresp/node()) + else + () + } + } + } +}; + + +(:~ + : Renders the table for integrations with brackets facing down. + : + : @author Michelle Weidling + :) +declare function simple2xhtml:make-bottom-bracket-integration-table($corresp as node()*, +$target as node()*) { + element xhtml:table { + attribute class {"integration integration-bottom"}, + element xhtml:tr { + element xhtml:td { + simple2xhtml:recursion($corresp/node()) + } + }, + element xhtml:tr { + element xhtml:td { + attribute class {"integration-bottom-bracket"}, + text{"⏟"} + } + }, + element xhtml:tr { + element xhtml:td { + simple2xhtml:recursion($target/node()) } } + } }; +(:~ + : A final decluttering of broken white spaces. + : :) declare function simple2xhtml:tidy($nodes as node()*) as node()* { for $node in $nodes return typeswitch ($node) @@ -684,3 +1097,58 @@ declare function simple2xhtml:tidy($nodes as node()*) as node()* { simple2xhtml:tidy($node/node()) } }; + + +(:~ Creates an icon and a modal window for an editorial or authorial comment. + : + : @author Michelle Weidling + : @param $node a tei:ptr or tei:note[@type = 'authorial'] + : @return an icon as xhtml:i and a modal window as xhtml:div + :) +declare function simple2xhtml:make-modal($node) as element(*)* { + let $content := + if($node[ancestor::tei:ab[@type = "sketch"]]) then + $node/ancestor::tei:ab[@type = "sketch"]//tei:figDesc//text()[not(./ancestor::tei:index)] + => string-join(" ") + => simple2xhtml:fix-whitespaces() + + else if($node[self::tei:note]) then + simple2xhtml:recursion($node/node()) + + else if($node[self::tei:ptr]) then + let $corresp-node := $node/root()//*[@target = "#" || $node/@reference] + return + simple2xhtml:recursion($corresp-node/node()) + + else + () + + let $id := util:hash(generate-id($node), "md5") + let $target := "#" || $id + return + if($content) then + ( + , + + ) + else + () +}; diff --git a/modules/fontane/edited-text/sort.xqm b/modules/fontane/edited-text/sort.xqm index 82a844d66147ebb0620d5df5777f33bfcf7fd0ca..a5724bc86f85b6d70f0375d71aaa188240ea4b11 100644 --- a/modules/fontane/edited-text/sort.xqm +++ b/modules/fontane/edited-text/sort.xqm @@ -14,24 +14,28 @@ 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"; +import module namespace functx="http://www.functx.com"; (:~ : The main function. Sorts each notebook and saves a sorted version at - : /db/sade-projects/textgrid/data/xml/print/xml/notebook_uri-presort.xml. + : /db/sade-projects/textgrid/data/xml/print/xml/notebook_uri-sorted.xml. : : @author Michelle Weidling :) -declare function fsort:main($tei as node()*, $log as xs:string) as element(tei:TEI) { - let $prepared := presort:prepare($tei) - let $prepared := fsort:enhance-handshifts($prepared, $log) - let $tei := fsort:sort($prepared, $log) - 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 -}; + declare function fsort:main($tei as node()*, $log as xs:string) as element(tei:TEI) { + let $prepared := fsort:prepare($tei) + let $prepared := fsort:enhance-handshifts($prepared, $log) + let $prepared := fsort:sort-certain-anchors($prepared, $log) + let $fully-sorted := fsort:sort($prepared, $log) + let $integrations := fsort:sort-integrations($fully-sorted, $log) + let $transpositions := fsort:sort-transpositions($integrations, $log) + let $multiphrases := fsort:sort-multiphrases($transpositions, $log) + let $marked := fsort:mark-referenced-elements($multiphrases, $log) + let $id := $tei/@id + + let $store := xmldb:store($config:data-root || "/print/xml/", $id || "-sorted.xml", $marked) + return $marked + }; (:~ @@ -63,40 +67,14 @@ declare function fsort:sort($nodes as node()*, $log as xs:string) { case element(tei:rs) return fsort:default-return($node, $log) -(: case element(tei:hi) return:) -(: if($node/@next and not($node/ancestor::tei:rs)) then:) -(: let $corresp-node := fsort:find-corresp-node($node, "next"):) -(: return:) -(: (: it's not sufficient to copy only the corresp node since:) -(: this would mean we'd loose the information about the tei:rs :):) -(: if($corresp-node[self::tei:hi and parent::tei:rs]) then:) -(: (fsort:keep-node($node),:) -(: element {QName("http://www.tei-c.org/ns/1.0", "rs")} {:) -(: $corresp-node/parent::*/@*,:) -(: $corresp-node:) -(: }):) -(: else:) -(: fsort:default-return($node):) -(: else:) -(: fsort:default-return($node):) -(::) -(::) -(: case element(tei:rs) return:) -(: (: in this case the tei:rs is empty after fsort:apply-all-nexts. we:) -(: don't need these. :):) -(: if($node[child::*[@prev]] and count($node/child::*) = 1) then:) -(: ():) -(: else:) -(: fsort:default-return($node):) -(: :) -(: case element(tei:date) return:) -(: fsort:keep-node($node):) -(::) -(: case element(tei:ref) return:) -(: fsort:keep-node($node):) + case element(tei:abbr) return + fsort:default-return($node, $log) + + case element(tei:anchor) return + fsort:default-return($node, $log) default return - fsort:keep-node($node, "sort", $log) + fsort:copy-node($node, "sort", $log) }; (:~ @@ -116,22 +94,29 @@ declare function fsort:default-return($node as node(), $log as xs:string) as nod or similar), their @prev/@next doesn't indicate the chronology but only the continuation of the highlighting. they should thus be omitted.:) if(matches($node/@style, "underline")) then - fsort:keep-node($node, "sort", $log) + fsort:copy-node($node, "sort", $log) else if($node[@next and not(@prev)]) then fsort:apply-all-nexts($node, $log) (: since all parts of the virtual aggregation are handled by fsort:apply-all-nexts - we can ignore the ones that have a @prev :) - else if($node[@prev]) then - () + we can ignore the ones that have a @prev. + this doesn't hold for the ones with a @anchor, since they are the first real + element of a virtual aggregation that has been started by an anchor when we + have an addition in a page's margin (3.21.13.3) :) + else if($node[@prev] + and not($node/@anchor = "true")) then + if($node/descendant::*[last()][self::tei:handShift]) then + fsort:copy-node($node/descendant::*[last()][self::tei:handShift], "sort", $log) + else + () (: we distinguish this case and the one below to improve performance :) else if($node[descendant::*[@next or @prev]]) then - fsort:keep-node($node, "sort", $log) + fsort:copy-node($node, "sort", $log) (: nodes with this attribute are part of an interlinear addition; they have - been marked by presort:prepare. since interlinear additions are handled as a + been marked by fsort:prepare. since interlinear additions are handled as a whole and put into the right place, their elements can be safely dumped here :) else if($node[@type = "interlinear"]) then () @@ -161,15 +146,16 @@ declare function fsort:apply-all-nexts($node as node(), $log as xs:string) as no return for $node-inbetween in $nodes-inbetween return - fsort:keep-node($node-inbetween, "sort", $log) + fsort:copy-node($node-inbetween, "sort", $log) else (: first element of a virtual aggregation: entry point :) - if($node/@next and not($node/@prev)) then + if($node/@next and not($node/@prev) + or ($node/@next and $node/ancestor::tei:seg[@type = "integration"])) then let $next-node := fsort:find-corresp-node($node, "next") return if(count($next-node) = 1) then - (fsort:keep-node($node, "sort", $log), + (fsort:copy-node($node, "sort", $log), (: check if the parts are in different lines :) if($node/ancestor::tei:line = $next-node/ancestor::tei:line) then () @@ -177,16 +163,34 @@ declare function fsort:apply-all-nexts($node as node(), $log as xs:string) as no element tei:milestone { attribute unit {"line"} }, - fsort:apply-all-nexts($next-node, $log)) + if($next-node/ancestor::tei:seg/@xml:lang) then + element tei:milestone { + attribute unit {"handshift"}, + attribute script {"Latn"} + } + else + (), + fsort:apply-all-nexts($next-node, $log), + if($next-node/ancestor::tei:seg/@xml:lang) then + element tei:milestone { + attribute unit {"handshift"}, + attribute script {"Latf"} + } + else + () + ) else if(not($next-node)) then - fsort:add-log-entry($log, "No next node found for " || $node/@next) + ( + fsort:copy-node($node, "sort", $log), + fsort:add-log-entry($log, "No next node found for " || $node/@next) + ) else fsort:add-log-entry($log, "Several next nodes found for " || $node/@next) (: last of a virtual aggregation: exit point :) else if(not($node/@next)) then - ($node/preceding::tei:handShift[1], - fsort:keep-node($node, "sort", $log)) + ($node/preceding::*[self::tei:handShift or self::tei:milestone[@unit = "handshift"]][1], + fsort:copy-node($node, "sort", $log)) (: element in the middle of a virtual aggregation:) else @@ -195,7 +199,7 @@ declare function fsort:apply-all-nexts($node as node(), $log as xs:string) as no return if(count($next-node) = 1) then ($prev-handshift, - fsort:keep-node($node, "sort", $log), + fsort:copy-node($node, "sort", $log), (: check if the parts are in different lines :) if($node/ancestor::tei:line = $next-node/ancestor::tei:line) then () @@ -225,15 +229,25 @@ declare function fsort:apply-all-nexts($node as node(), $log as xs:string) as no : @param $node the current node : @return a copy of the current node with sorted descendants :) -declare function fsort:keep-node($node as node(), $flag as xs:string, $log as xs:string) as node() { + declare function fsort:copy-node($node as node(), $flag as xs:string, $log as xs:string) as node() { element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { $node/@*, if($flag = "sort") then fsort:sort($node/node(), $log) - else + else if($flag = "handshift") then fsort:enhance-handshifts($node/node(), $log) - } -}; + else if($flag = "sort-integrations") then + fsort:sort-integrations($node/node(), $log) + else if($flag = "sort-transpositions") then + fsort:sort-transpositions($node/node(), $log) + else if($flag = "sort-multiphrases") then + fsort:sort-multiphrases($node/node(), $log) + else if($flag = "sort-certain-anchors") then + fsort:sort-certain-anchors($node/node(), $log) + else + error(QName("FONTANE", "fsort2"), "Invalid flag: " || $flag || "." ) + } + }; @@ -255,62 +269,6 @@ declare function fsort:get-id($target as xs:string) as xs:string { }; -(:~ - : tei:rs oftentimes has one or several element(s) as descendant(s) which can be in - : the middle or end of a virtual aggregation. These have already been handled by - : sort:apply-all-nexts and should therefore not be considered. - : - : @author Michelle Weidling - : @param $node the current tei:rs - : @return tei:rs - :) -declare function fsort:exclude-copied($node as element(tei:rs)) as -element(tei:rs)? { - if(fsort:has-only-copied-children($node)) then - () - else - let $rs-children := $node/node() - let $processed-children := - for $child in $rs-children return - if($child/@next - and not(matches($child/@style, "underline"))) then - fsort:apply-all-nexts($child, $log) - else - $child - - return - if(count($processed-children) gt 0) then - element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { - $node/@*, - $processed-children - } - else - () -}; - -(:~ - : tei:rs oftentimes has one or several element(s) as descendant(s) which can be part - : of a virtual aggregation. If this applies to all children of tei:rs, all of them - : have been handled by fsort:apply-all-nexts, thus leaving the tei:rs empty. - : - : In these cases we need an indicator if we can savely drop a tei:rs. - : - : @author Michelle Weidling - : @param $node the current tei:rs - : @return xs:boolean - : :) -declare function fsort:has-only-copied-children($node as element()) as -xs:boolean { - let $are-copied := - for $desc in $node//node() return - if($desc[@prev]) then - true() - else - false() - return - not($are-copied = false()) -}; - declare function fsort:add-log-entry($log-file as xs:string, $message as xs:string) as empty-sequence() { @@ -351,12 +309,293 @@ as node()* { else attribute medium {$node/preceding::tei:handShift[@medium][1]/@medium}, - if($node/@script) then + if($node/@script + and (matches($node/@script, "Lat") or matches($node/@script, "Druck"))) then $node/@script + else if($node/@script) then + let $prev-hs := $node/preceding::tei:handShift[1]/@script + return + attribute script {string-join(($node/@script, $prev-hs), " ")} else attribute script {$node/preceding::tei:handShift[@script][1]/@script} } default return - fsort:keep-node($node, "handshift", $log) + fsort:copy-node($node, "handshift", $log) +}; + + +(:~ + : Marks all nodes that are part of an interlinear addition. + : + : @author Michelle Weidling + : @param $node The current node + : @return The processed node + :) +declare function fsort:prepare($nodes as node()*) as node()* { + for $node in $nodes + return + typeswitch ($node) + case text() return + $node + + case comment() return + if(matches($node/string(), "rotate")) then + $node + else + () + + default return + if($node/preceding-sibling::*[self::tei:addSpan][1][@place = 'interlinear'][@prev or @next] + and not($node[self::tei:anchor])) then + fsort:mark-interlinear-node-to-be-moved($node) + else + element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + $node/@*, + fsort: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 fsort: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 fsort:sort-integrations($nodes as node()*, $log as xs:string) as node()* { + for $node in $nodes return + if($node/@xml:id) then + let $id := $node/@xml:id + let $metamarks := $node/root()//tei:metamark[@function = ("integrate", "authorial_note")] + 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 tei:seg { + attribute type {"integration"}, + $integration-comment, + $linking-node-corresp, + fsort:copy-node($node, "sort-integrations", $log) + } + else if($linking-node-target) then + () + else + fsort:copy-node($node, "sort-integrations", $log) + + else if($node[self::tei:metamark[@function = "integrate"]]) then + () + else if($node[self::text() or self::comment()]) then + $node + else + fsort:copy-node($node, "sort-integrations", $log) +}; + + +(:~ In some cases we have text that is transposed, i.e. two or more areas of + : text that are switched. The correct order of the texts is denoted in a tei:listTranspose. + : This function serves restore the intended order by setting the sequence of texts + : of tei:listTranspose when the first transposed element is met. + : + : @author Michelle Weidling + : @param $nodes the nodes to be processed + : @param path to log file + : @return the processed nodes. transpositions are put in the right order, the rest is kept as is :) +declare function fsort:sort-transpositions($nodes as node()*, $log as xs:string) as node()* { + for $node in $nodes return + + if(fsort:is-transposed($node) + and fsort:is-first-transposed($node)) then + let $transposed-order-ids := + for $ptr in $node/root()//tei:transpose/tei:ptr return + replace($ptr/@target, "#", "") => tokenize(" ") + + + return + element tei:seg { + attribute type {"transposed"}, + for $id in $transposed-order-ids return + let $corresp-node := $node/root()//*[@xml:id = $id] + return fsort:copy-node($corresp-node, "sort-transpositions", $log) + } + + else if(fsort:is-transposed($node) + or $node[self::tei:listTranspose]) then + () + + else if($node[self::text() or self::comment()]) then + $node + + else + fsort:copy-node($node, "sort-transpositions", $log) +}; + + +(:~ Checks if a node with an xml:id is transposed or not. + : + : @author Michelle Weidling + : @param $node A node with an xml:id + : @return true() when the node's xml:id is mentioned in tei:listTranspose, false() otherwise + :) +declare function fsort:is-transposed($node as node()*) as xs:boolean { + let $id := $node/@xml:id + let $transpositions := $node/root()//tei:transpose/tei:ptr + let $transpo-ids := for $ptr in $transpositions return + replace($ptr/@target, "#", "") => tokenize(" ") + + return $id = $transpo-ids +}; + + +(:~ Checks if a node with an xml:id is the first transposed element in a + : tei:listTranspose. + : + : @author Michelle Weidling + : @param $node A node with an xml:id + : @return true() when the node's xml:id is the first transposed element, false() otherwise + :) +declare function fsort:is-first-transposed($node as node()*) as xs:boolean { + let $first-transposed-id := replace($node/root()//tei:transpose/tei:ptr[1]/@target, "#", "") => tokenize(" ") + return $node/@xml:id = $first-transposed-id[1] +}; + + +(:~ In some cases we have text two or more longer variations of a text passage, + : e.g. in a draft for a piece of literature. These passages should be marked as + : different layers of text and have to be put into the right order. + : + : @author Michelle Weidling + : @param $nodes the nodes to be processed + : @param path to log file + : @return the processed nodes. transpositions are put in the right order, the rest is kept as is :) +declare function fsort:sort-multiphrases($nodes as node()*, $log as xs:string) as node()* { + for $node in $nodes return + if($node[self::tei:addSpan[@type = "multiphrase" and @subtype = "extensive"]]) then + let $corresp-id := replace($node/@spanTo, "#", "") + let $corresp-node := $node/root()//*[@xml:id = $corresp-id] + + return + element tei:div { + attribute type {"multiphrase"}, + for $inbetween in $node/following-sibling::*[. << $corresp-node] return + fsort:copy-node($inbetween, "sort-multiphrases", $log), + $corresp-node + } + + else if($node[self::text() or self::comment()]) then + $node + + else + let $addSpan := $node/preceding-sibling::tei:addSpan[@type = "multiphrase" and @subtype = "extensive"] + let $anchor := $addSpan/root()//*[@xml:id = replace($addSpan/@spanTo, "#", "")] + + return + if($addSpan and $node/following::*[$anchor]) then + () + else + fsort:copy-node($node, "sort-multiphrases", $log) +}; + +declare function fsort:sort-certain-anchors($nodes as node()*, $log as xs:string) as node()* { + for $node in $nodes return + typeswitch ($node) + + case element(tei:anchor) return + if($node/@next) then + let $corresp-node := fsort:find-corresp-node($node, "next") + return if($corresp-node/preceding-sibling::*[1][self::tei:addSpan[@place = "margin"]]) then + fsort:apply-only-next-node($corresp-node, $log) + else + $node + + else + $node + + default return + if($node[self::text() or self::comment()]) then + $node + + else + fsort:copy-node($node, "sort-certain-anchors", $log) +}; + +declare function fsort:apply-only-next-node($node as node()*, $log as xs:string) as node()* { + element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + $node/(@* except @prev), + attribute anchor {"true"}, + fsort:sort-certain-anchors($node/node(), $log) + } +}; + + +(:~ adds an extra flag for the elements that are referenced in the editorial + : TOC. :) +declare function fsort:mark-referenced-elements($nodes as node()*, $log as xs:string) +as node()* { + for $node in $nodes return + typeswitch ($node) + + case text() return + $node + + case comment() return + $node + + default return + element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + $node/@*, + let $refs := $node/root()//tei:list[@type = "editorial"]//tei:ref[@type] + let $referenced-ids := + for $ref in $refs return + let $tokens := tokenize($ref/@target, " ") + let $tokens := $tokens[2] + for $token in $tokens return + substring-after($token, "@xml:id='") + => substring-before("']") + return + if($node/@xml:id = $referenced-ids) then + attribute subtype {"referenced"} + else + (), + fsort:mark-referenced-elements($node/node(), $log) + } }; diff --git a/modules/fontane/edited-text/tei2teisimple.xqm b/modules/fontane/edited-text/tei2teisimple.xqm index 4a7239c46fc25724dc720c640722d61d28f38843..fe223d1f5fedf7848b1c611949d3aa1e9fa4532b 100644 --- a/modules/fontane/edited-text/tei2teisimple.xqm +++ b/modules/fontane/edited-text/tei2teisimple.xqm @@ -13,10 +13,7 @@ xquery version "3.1"; module namespace fontaneSimple="http://fontane-nb.dariah.eu/teisimple"; -declare namespace svg="http://www.w3.org/2000/svg"; declare namespace tei="http://www.tei-c.org/ns/1.0"; -declare namespace test="http://exist-db.org/xquery/xqsuite"; -declare namespace xlink="http://www.w3.org/1999/xlink"; import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm"; import module namespace functx="http://www.functx.com"; @@ -27,19 +24,9 @@ import module namespace index-info="http://fontane-nb.dariah.eu/index-info" at " (:~ : The main function initiates the transformation of a given notebook. : - : TODO: adapt to several input files? - : : :) declare function fontaneSimple:main($doc as node()*, $uri as xs:string, $log as -xs:string) as node()? { -(:declare function fontaneSimple:main($file as xs:string) as node()? {:) -(: let $doc :=:) -(: try {:) -(: (doc("/db/sade-projects/textgrid/data/xml/data/" || $file)):) -(: } catch * {:) -(: (console:log("It was not possible to open the requested file " || $file)):) -(: }:) - +xs:string) as element(tei:teiCorpus) { let $front-covers := $doc//tei:sourceDoc/tei:surface[contains(@n, "front_cover")] let $back-covers := $doc//tei:sourceDoc/tei:surface[contains(@n, "back_cover")] let $content := ($doc//tei:sourceDoc/tei:surface[not(contains(@n, "cover") @@ -85,13 +72,15 @@ $log as xs:string) as node()* { or $node/ancestor::tei:figDesc or $node/ancestor::tei:desc[@type = "edited_text"] or $node/ancestor::tei:note[@type = "editorial"] - or $node/ancestor::tei:seg[@type = "editorial-label"] - or $node/ancestor::tei:ref[not(matches(@target, "getty") or matches(@target, "xpath"))]) then - if($node/parent::tei:rs and starts-with($node, " ") - and not($node/preceding-sibling::*[1][self::tei:handShift or self::tei:hi]) - and simpleHelpers:is-trimming-necessary($node)) then - simpleHelpers:prepare-text(text{substring-after($node, " ")}) - else + or $node/ancestor::tei:note[@type = "authorial" and @subtype = ("footnote", "revision", "text")] + or $node/ancestor::tei:seg[@type = ("editorial-label", "integration")] + or $node/ancestor::tei:ref[not(matches(@target, "getty") or matches(@target, "xpath"))] + or $node/ancestor::tei:seg[@type = "heading"]) then +(: if($node/parent::tei:rs and starts-with($node, " "):) +(: and not($node/preceding-sibling::*[1][self::tei:handShift or self::tei:hi]):) +(: and simpleHelpers:is-trimming-necessary($node)) then:) +(: simpleHelpers:prepare-text(text{substring-after($node, " ")}):) +(: else:) simpleHelpers:prepare-text($node) else () @@ -103,9 +92,14 @@ $log as xs:string) as node()* { else if($node/ancestor::tei:seg[@type = "editorial-label"]) then text{" "} - else if($node[@break = "no"]) then + else if($node[@break = "no"] + and not($node/preceding-sibling::tei:line[1]/child::*[last()][self::tei:choice])) then fontaneSimple:mark-intervention($node, $uri, $log) + else if($node[@break = "no"] + and $node/preceding-sibling::tei:line[1]/child::*[last()][self::tei:choice]) then + () + else fontaneSimple:copy-element($node, $uri, $log) @@ -149,22 +143,46 @@ $log as xs:string) as node()* { else if($node/@cause = "unclear") then () - else if($node[replace($node/@copyOf, "#", "") = $node/ancestor::tei:TEI//tei:seg/@xml:id]) then - fontaneSimple:mark-intervention($node, $uri, $log) - else if($node/@cause ="catchword") then () + else if($node[replace($node/@copyOf, "#", "") = $node/root()//tei:seg/@xml:id]) then + fontaneSimple:mark-intervention($node, $uri, $log) + else if($node/@rend ="|") then fontaneSimple:transform($node/node(), $uri, $log) - else if($node/@place = "above" - and $node/preceding::node()[1][normalize-space(.) = ""]) then - (text{" "}, - fontaneSimple:transform($node/node(), $uri, $log)) + else if($node/@place = ("above", "below") +(: and :) +(: ( :) +(: $node/preceding::node()[1][normalize-space(.) = ""]:) +(: or $node/ancestor::tei:seg[@type = "transposed"]):) +(: or ends-with($node/preceding-sibling::*[1][self::tei:del], ","):) + ) + then + ( + if(not($node/preceding-sibling::node()[1][self::text()][matches(substring(., string-length(.), 1), "[a-z]")]) + and not($node/preceding-sibling::*[1][self::tei:del])) then + text{" "} + else + (), + fontaneSimple:transform($node/node(), $uri, $log), + if($node/following::node()[1][normalize-space(.) = ""] + or $node/ancestor::tei:seg[@type = "transposed"] + or matches(substring($node/following::text()[1],1 ,1), "[A-Z]")) then + text{" "} + else + () + ) else if($node[@place = "superimposed"]) then - fontaneSimple:preserve-whitespace($node, $uri, $log) + ( + if(ends-with($node/preceding-sibling::*[1][self::tei:del], ",")) then + text{" "} + else + (), + fontaneSimple:transform($node/node(), $uri, $log) + ) else if(not($node/@xml:id)) then @@ -200,43 +218,40 @@ $log as xs:string) as node()* { or matches($node/@rendition, "roman")) then fontaneSimple:make-seg-with-rendition($node, $uri, $log) - else if($node/following::*[1][self::tei:lb[@break = "no"]]) then + else if($node/following::*[1][self::tei:lb[@break = "no"]] + and not($node/child::*[last()][self::tei:choice])) then (simpleHelpers:start-line($node), simpleHelpers:trim-last-char($node)) - else if ($node/preceding::*[1][self::tei:lb[@break = "no"]]) then + else if($node/preceding::*[1][self::tei:lb[@break = "no"]] + and not($node/child::*[1][self::tei:choice])) then (simpleHelpers:start-line($node), simpleHelpers:trim-first-char($node)) - else if($node/@type = "verse") then + else if($node/@type = "verse" + or $node/ancestor::tei:zone[@type = "verse"]) then if($node/@prev) then () else if(not($node/@next)) then - (if(not($node/preceding-sibling::tei:line[@type = "verse"])) then - fontaneSimple:mark-linegroup-beginning() - else - (), element tei:l { + if($node/@rend) then + attribute subtype {$node/@rend} + else + (), fontaneSimple:transform($node/node(), $uri, $log) - }, - if(not($node/following-sibling::tei:line[@type = "verse"])) then - fontaneSimple:mark-linegroup-end() - else - ()) + } (: 3.8.2.2.1.3 Vers mit anderer Beschriftung in einer Zeile :) else let $corresp := $node/following::*[@type = "verse" and replace($node/@next, "#", "") = @xml:id] return - (fontaneSimple:mark-linegroup-beginning(), element tei:l { fontaneSimple:transform($node/node(), $uri, $log), simpleHelpers:start-line($node), fontaneSimple:transform($corresp/node(), $uri, $log) - }, - fontaneSimple:mark-linegroup-end()) + } else if($node/parent::tei:zone[@type = "verse"]/child::*[1] = $node) then fontaneSimple:transform($node/node(), $uri, $log) @@ -285,8 +300,15 @@ $log as xs:string) as node()* { else if($node/@type = "heading") then fontaneSimple:make-head($node, $uri, $log) + else if($node[@style = "text-decoration:underline" and @rend = "underline-medium:blue_pencil"]) then + element tei:seg { + attribute type {"blue-underlined"}, + fontaneSimple:transform($node/node(), $uri, $log) + } + + else if(matches($node/@style, "underline") - and not(matches($node/@style, "vertical-align"))) then + and not(simpleHelpers:has-valid-style($node))) then fontaneSimple:transform($node/node(), $uri, $log) else if(simpleHelpers:has-valid-style($node) @@ -297,6 +319,7 @@ $log as xs:string) as node()* { else if($node/@type = "initials" or $node/@type = "monogram" or $node/@type = "multiphrase" + or $node/@type = "highlighted-area" or $node/@xml:lang) then (fontaneSimple:copy-element($node, $uri, $log), @@ -312,11 +335,9 @@ $log as xs:string) as node()* { then () - else if($node/parent::tei:add and $node/@copyOf) then + else if($node/ancestor::tei:add and $node/@copyOf) then fontaneSimple:mark-intervention($node, $uri, $log) - else if($node/@type = "verse" and $node/@prev) then - () else if($node/@type = "said") then if($node/@next) then @@ -347,7 +368,13 @@ $log as xs:string) as node()* { fontaneSimple:transform($node/node(), $uri, $log) } - else if($node/@type = ("integration", "editorial-label")) then + else if($node/@type = ("integration", "editorial-label", "col", "marked_off", "transposed")) then + element tei:seg { + $node/@*, + fontaneSimple:transform($node/node(), $uri, $log) + } + + else if($node/@xml:id) then element tei:seg { $node/@*, fontaneSimple:transform($node/node(), $uri, $log) @@ -357,16 +384,25 @@ $log as xs:string) as node()* { fontaneSimple:transform($node/node(), $uri, $log) case element(tei:hi) return - (element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { - $node/@*, - fontaneSimple:transform($node/node(), $uri, $log) - }, - if(not($node/@prev or $node/@next) - and $node/following::node()[1][self::text()][normalize-space(.) = ""] - and $node/following::*[1][self::tei:hi]) then - text{"@"} + if($node/ancestor::tei:seg[@style = "text-decoration:underline" and @rend = "underline-medium:blue_pencil"] + or $node/descendant::tei:seg[@style = "text-decoration:underline" and @rend = "underline-medium:blue_pencil"]) then + element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + $node/@*, + attribute type {"blue-underlined"}, + fontaneSimple:transform($node/node(), $uri, $log) + } + else - () + (element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + $node/@*, + fontaneSimple:transform($node/node(), $uri, $log) + }, + if(not($node/@prev or $node/@next) + and $node/following::node()[1][self::text()][normalize-space(.) = ""] + and $node/following::*[1][self::tei:hi]) then + text{"@"} + else + () ) (: TODO if $node/@type = "highlighted" then make @@ -376,8 +412,8 @@ $log as xs:string) as node()* { if($node/@type = "highlighted" and simpleHelpers:is-hand-contemporary($node/@hand)) then $node - else if($node/following::node()[1][self::text()]) then - fontaneSimple:preserve-whitespace($node, $uri, $log) +(: else if($node/following::node()[1][self::text()]) then:) +(: fontaneSimple:preserve-whitespace($node, $uri, $log):) else fontaneSimple:transform($node/node(), $uri, $log) @@ -405,16 +441,16 @@ $log as xs:string) as node()* { and $node/@type = "clipping") then if($node/@subtype = "Kalenderblatt" and contains($node//tei:handShift/@new, "Friedrich_Fontane")) then + (fontaneSimple:make-pb($node), element tei:div { $node/@n, attribute type {$node/@subtype}, fontaneSimple:transform($node/node(), $uri, $log) - } + }) - else if(not($node/@subtype = "Kalenderblatt" - or $node/@subtype = "Zeitungsausschnitt_Fragment")) then + else if(not($node/@subtype = "Kalenderblatt")) then element tei:div { - $node/(@* except (@n, @ulx, @uly, @lry, @lrx)), + $node/(@* except (@n, @ulx, @uly, @lry, @lrx, @facs)), fontaneSimple:transform($node/node(), $uri, $log) } @@ -422,12 +458,20 @@ $log as xs:string) as node()* { () else if(simpleHelpers:is-page($node)) then - (text{" "}, - fontaneSimple:transform($node/node(), $uri, $log)) + ( + if(ends-with($node//text()[matches(., "[\w]")][last()], "-") + or ends-with($node//text()[matches(., "[\w]")][last()], "⸗")) then + () + else + text{" "}, + fontaneSimple:transform($node/node(), $uri, $log) + ) else if($node/@type = "label" and (contains($node/@subtype, "Fontane") - or contains($node/@subtype, "Hersteller")) + or contains($node/@subtype, "Hersteller") + or contains($node/@subtype, "Firmen")) + and not($node/@attachment = "glued-posthumous") ) then fontaneSimple:make-div($node, $uri, $log) @@ -437,22 +481,32 @@ $log as xs:string) as node()* { case element(tei:milestone) return if($node/@unit = "illustration") then () + (: during sort.xqm we already create handshifts, but they lack + information about who if the author. :) + else if($node/@unit = "handshift") then + fontaneSimple:enhance-handshift($node) else fontaneSimple:copy-element($node, $uri, $log) case element(tei:gap) return fontaneSimple:copy-element($node, $uri, $log) + case element(tei:supplied) return + fontaneSimple:mark-supplied($node, $uri, $log) + case element(tei:metamark) return - if($node/@function = "integrate" - or $node/@function = "authorial_note") then + if($node/@function = ("integrate", "authorial_note")) then element tei:ab { $node/@* } - else if($node/@function = ("placeholder", "etc.", "caret", - "footnote-mark", "footnotes", "ellipsis", "paragraph")) then + else if($node/@function = ("placeholder", "etc.", + "footnote-mark", "footnotes", "ellipsis", "paragraph", "verse_marker")) then element tei:ab { attribute type {$node/@function}, + if($node/@function = "verse_marker") then + attribute rend {$node/@rend} + else + (), fontaneSimple:transform($node/node(), $uri, $log) } else @@ -462,11 +516,19 @@ $log as xs:string) as node()* { fontaneSimple:mark-intervention($node, $uri, $log) case element(tei:zone) return + ( + if($node/@subtype = "referenced") then + element tei:ab { + $node/@xml:id, + attribute type {"referenced"} + } + else + (), if(matches($node/@style, "border-style:solid") and not(matches($node/@style, "border-radius")) and not($node/@rend = "border-style:house")) then - element tei:div { - attribute type {"frame"}, + element tei:seg { + attribute type {"framed"}, fontaneSimple:transform($node/node(), $uri, $log) } @@ -480,9 +542,8 @@ $log as xs:string) as node()* { () else if($node/@type = "marked_off") then - element tei:seg { - $node/@type, - $node/@xml:id, + element tei:div { + $node/(@type, @xml:id, @next, @prev), fontaneSimple:transform($node/node(), $uri, $log) } @@ -491,15 +552,12 @@ $log as xs:string) as node()* { fontaneSimple:transform($node/node(), $uri, $log) else element tei:hi { - $node/@xml:id, - $node/@prev, - $node/@next, + $node/(@xml:id, @prev, @next), attribute type {"vertical-mark"}, fontaneSimple:transform($node/node(), $uri, $log) } - else if($node/@type = "illustration" - or $node/@type = "printed_illustration") then + else if($node/@type = ("illustration", "printed_illustration")) then if(not($node//tei:figure/parent::tei:del)) then element tei:ab { (if($node/child::tei:zone[@type = "illustration"]) then @@ -509,19 +567,27 @@ $log as xs:string) as node()* { if($node/parent::tei:zone[@type = "illustration"]) then attribute rendition {"margin-left:" || $node/@ulx || "cm; " || "margin-top:" || $node/@uly || "cm"} + else + (), + if($node/ancestor::tei:surface/@next and not($node/@xml:id)) then + (attribute xml:id {$node/ancestor::tei:surface/@xml:id}, + attribute next {$node/ancestor::tei:surface/@next}) + else if($node/ancestor::tei:surface/@prev and not($node/@xml:id)) then + (attribute xml:id {$node/ancestor::tei:surface/@xml:id}, + attribute prev {$node/ancestor::tei:surface/@prev}) else () ) ), attribute width {$node/@lrx - $node/@ulx || "cm"}, attribute height {$node/@lry - $node/@uly || "cm"}, + $node/(@xml:id), fontaneSimple:transform($node/node(), $uri, $log) } else () - else if($node/parent::tei:zone/@type = "illustration" - or $node/parent::tei:zone/@type = "printed_illustration") then + else if($node/parent::tei:zone/@type = ("illustration", "printed_illustration")) then element tei:seg { attribute type {"caption"}, fontaneSimple:transform($node/node(), $uri, $log) @@ -531,7 +597,19 @@ $log as xs:string) as node()* { fontaneSimple:make-head($node, $uri, $log) else if($node/@type = "list" - or $node/@type = "item") then + and $node//tei:seg[@type = "col"]) then + element tei:table { + $node/@*, + for $line in $node/tei:line[descendant::tei:seg[@type = "col"]] return + element tei:row { + for $seg in $line/descendant::tei:seg[@type = "col"] return + element tei:cell { + fontaneSimple:transform($seg/node(), $uri, $log) + } + } + } + + else if($node/@type = ("list", "item")) then element {QName("http://www.tei-c.org/ns/1.0", $node/@type)} { $node/(@xml:id, @subtype, @rendition, @prev, @next), if($node/@rend) then @@ -541,25 +619,19 @@ $log as xs:string) as node()* { fontaneSimple:transform($node/node(), $uri, $log) } - else if($node/@type = "dialogue") then + else if($node/@type = ("dialogue", "edited_text", "multiphrase")) then element tei:div { - $node/@type, + $node/@*, fontaneSimple:transform($node/node(), $uri, $log) } - else if($node/@type = "verse") then - (fontaneSimple:mark-linegroup-beginning(), - element tei:l { - fontaneSimple:transform($node/node(), $uri, $log) - }, - fontaneSimple:mark-linegroup-end()) - - else if($node/@type = "said" and $node/@prev) then - () - - else if($node/@type = "said") then + else if($node/@type = ("verse", "said")) then element tei:seg { - $node/@type, + attribute type {$node/@type}, + if($node/@rend) then + attribute subtype {$node/@rend} + else + (), fontaneSimple:transform($node/node(), $uri, $log) } @@ -569,7 +641,7 @@ $log as xs:string) as node()* { else if($node/@type = "toc") then element tei:div { - $node/(@type, @subtype), + $node/(@type, @subtype, @xml:id), fontaneSimple:transform($node/node(), $uri, $log) } @@ -596,24 +668,33 @@ $log as xs:string) as node()* { or matches($node/@rendition, "roman")) then fontaneSimple:make-seg-with-rendition($node, $uri, $log) + else if($node/@rend = "indent") then + element tei:div { + attribute type {$node/@rend}, + fontaneSimple:transform($node/node(), $uri, $log) + } + else if(not($node/@xml:id)) then fontaneSimple:transform($node/node(), $uri, $log) else if($node/@xml:id) then - ( -(: if($node/@xml:id = "C06_14r_9") then:) -(: util:log-system-out($node):) -(: else (),:) element tei:seg { $node/@xml:id, $node/@prev, $node/@next, $node/@corresp, fontaneSimple:transform($node/node(), $uri, $log) - }) + } + + else if($node/@rend) then + element tei:seg { + attribute subtype {$node/@rend}, + fontaneSimple:transform($node/node(), $uri, $log) + } else fontaneSimple:transform($node/node(), $uri, $log) + ) case element(tei:said) return (element tei:seg { @@ -628,32 +709,20 @@ $log as xs:string) as node()* { ()) case element(tei:figure) return -(: if(count($node/child::*) = 2 :) -(: and $node/child::tei:figDesc:) -(: and $node/child::tei:ptr) then:) - (: genealogy lines probably shouldn't be displayed, but I still have to - check that. in case they should be serialized, I leave the code :) -(: if(matches($node/descendant::tei:ref, "Stammbaumverbindungslinie")) then:) -(: element tei:seg {:) -(: $node/@*,:) -(: fontaneSimple:transform($node/node(), $uri, $log):) -(: }:) -(: else if(matches($node/descendant::tei:ref, "Schlusslinie")):) - if(matches($node/descendant::tei:ref, "Schlusslinie")) - then - element tei:ab { - switch ($node/descendant::tei:ref) - case "horizontale einfache Schlusslinie" return - attribute type {"long-end-line"} - case "Schlusslinie; horizontale Halbschleife von links oben nach rechts" return - attribute type {"long-end-line"} - case "horizontale einfache Schlusslinie (gewellt)" return - attribute type {"long-end-line-wavy"} - case "Schlusslinien; horizontale Schleife von links oben nach rechts unten" return - attribute type {"bottom-brace-short"} - default return - attribute type {"end-line"} - } + if(matches($node/descendant::tei:ref, "Schlusslinie") + and not(matches($node/descendant::tei:ref, "ehemalig"))) + then + element tei:ab { + switch ($node/descendant::tei:ref) + case "horizontale einfache Schlusslinie" return + attribute type {"long-end-line"} + case "Schlusslinie; horizontale Halbschleife von links oben nach rechts" return + attribute type {"long-end-line"} + case "horizontale einfache Schlusslinie (gewellt)" return + attribute type {"long-end-line"} + default return + attribute type {"end-line"} + } else if(matches($node/descendant::tei:ref, "Absatzlinie") (: in case of double paragraph lines the single lines are @@ -669,55 +738,38 @@ $log as xs:string) as node()* { attribute type {"short-paragraph-line"} } - else if(matches($node/descendant::tei:ref, "horizontale einfache Abgrenzungslinie")) then + else if(matches($node/descendant::tei:ref, "doppelter Summenstrich")) then + element tei:ab { + attribute type {"double-sum"} + } + + else if(matches($node/descendant::tei:ref, "Summenstrich")) then + element tei:ab { + attribute type {"sum"} + } + + else if(matches($node/descendant::tei:ref, "Differenzstrich")) then + element tei:ab { + attribute type {"difference"} + } + + + (: 3.7.13.2 Nicht ermittelte Skizzen :) + else if(not($node/@xml:id)) then () - else if($node/ancestor::tei:zone[@type = "illustration"]) then - let $display := - if($node/ancestor::tei:zone[@type = "illustration"]/tei:milestone[@unit = "illustration"][. << $node]) then - "block" - else - "inline" - let $img-url := try {tbleapi:get-url($uri, $node/@xml:id, "png") } - catch * { fontaneSimple:add-log-entry($log, "No TBLE-file found for " || serialize($node)) } - let $img-url := - if($display = "inline") then - replace($img-url, ",1000", ",500") - else - $img-url - let $rotation := - (: no children and comment right after element:) - if($node/following-sibling::node()[1][self::comment()][matches(./string(), "rotate")] - and not($node/child::*)) then - substring-after($node/following::comment()[1], "rotate(") - => substring-before("deg") - (: comment as first descendant :) - else if($node/child::node()[1][self::comment()][matches(./string(), "rotate")]) then - substring-after($node/child::comment()[1], "rotate(") - => substring-before("deg") - else - () + else if($node/ancestor::tei:surface[@next or @prev]) then + fontaneSimple:make-img($node, $uri, $log,"double") - return - element {QName("http://www.tei-c.org/ns/1.0", $node/name())}{ - $node/@*, - attribute position {$display}, - attribute href {$img-url}, - if($rotation) then - attribute rotate {$rotation} - else - (), - fontaneSimple:transform($node/node(), $uri, $log) - } - else + else if($node/ancestor::tei:zone[@type = ("illustration", "printed_illustration")]) then + fontaneSimple:make-img($node, $uri, $log, "") + else () -(: else:) -(: fontaneSimple:copy-element($node, $uri, $log):) case element(tei:note) return if($node/@type = "authorial" - and not($node/@subtype = "footnote")) then + and not($node/@subtype = ("footnote", "text"))) then () else fontaneSimple:copy-element($node, $uri, $log) @@ -743,6 +795,8 @@ $log as xs:string) as node()* { case element(tei:choice) return if($node[ancestor::tei:seg[@type = "editorial-label"]]) then $node/tei:abbr + else if($node/tei:corr) then + fontaneSimple:mark-missing-syllable($node, $uri, $log) else fontaneSimple:copy-element($node, $uri, $log) @@ -770,7 +824,7 @@ $log as xs:string) as node()* { otherwise :) else if($node//text()[matches(., "[\w]")]) then ( - element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { $node/@*, if($node/@prev) then () @@ -874,7 +928,7 @@ $log as xs:string) as element(tei:head) { ), $node/@subtype, - + $node/@xml:id, (if($node//tei:hi) then attribute underlined {"true"} else @@ -885,10 +939,18 @@ $log as xs:string) as element(tei:head) { else ()), - (if($node/@rend) then + if($node/@rend) then $node/@rend else - ()), + (), + if($node/@next) then + $node/@next + else + (), + if($node/@prev) then + $node/@prev + else + (), fontaneSimple:transform($node/node(), $uri, $log) } }; @@ -960,33 +1022,17 @@ as element(tei:pb) { } }; -declare function fontaneSimple:enhance-handshift($node as element(tei:handShift)) + +declare function fontaneSimple:enhance-handshift($node as element(*)) as element(tei:milestone) { let $prev-hand := $node/preceding::tei:handShift[@new][1] - let $whitespace-before := - if($node/preceding::node()[1][normalize-space(.) = ""] - and string-length($node/preceding::text()[1]) = 1) then - true() - else - false() - - let $whitespace-after := - if($node/following::node()[1][normalize-space(.) = ""] - and string-length($node/following::text()[1]) = 1 - and not($node/following::*[1][@type = "heading"]) - and not($node/following::text()[1][matches(substring(., 1, 1), "[\.,]")])) then - true() - else - false() return element tei:milestone { attribute unit {"handshift"}, attribute subtype {if($node/@new) then $node/@new else $prev-hand/@new}, -(: (if($whitespace-before) then attribute ws-before {"true"} else ()),:) -(: (if($whitespace-after) then attribute ws-after {"true"} else ()),:) - $node/(@* except @new) + $node/(@* except (@new, @unit)) } }; @@ -994,25 +1040,51 @@ as element(tei:milestone) { declare function fontaneSimple:mark-intervention($node as element(*), $uri as xs:string, $log as xs:string) as element(tei:seg) { - element tei:seg { + let $type := if($node[self::tei:lb]) then - attribute type {"missing-hyphen"} + "missing-hyphen" else if($node[self::tei:surplus]) then - attribute type {"surplus"} + "surplus" else - attribute type {"reduplication"}, - - , + "reduplication" + return + element tei:seg { + attribute type {$type}, + , if($node[self::tei:lb]) then simpleHelpers:find-chars($node) else fontaneSimple:transform($node/node(), $uri, $log), - + } }; +declare function fontaneSimple:mark-missing-syllable($node as element(*), $uri as +xs:string, $log as xs:string) as element(tei:seg) { + let $sic := $node/tei:sic/string() + let $sic-length := string-length($sic) + let $corr := $node/tei:corr/string() + let $corr-length := string-length($corr) + + let $diff := $corr-length - $sic-length + let $missing := substring($corr, 1, $diff) + let $existent := $sic + + let $type := "missing-syllable" + + + return + element tei:seg { + attribute type {$type}, + , + $missing, + , + $existent + } +}; + declare function fontaneSimple:mark-missing-hyphen($node as element(tei:lb)) as element(tei:seg) { @@ -1024,6 +1096,16 @@ element(tei:seg) { } }; +declare function fontaneSimple:mark-supplied($node as element(tei:supplied), $uri as xs:string, $log as xs:string) as +element(tei:seg) { + element tei:seg { + attribute type {"supplied"}, + , + fontaneSimple:transform($node/node(), $uri, $log), + + } +}; + (:~ In this first serialization step the beginning and end of line groups are : simply marked with milestones, which are expanded to a full tei:lg in the @@ -1332,3 +1414,83 @@ $message as xs:string) as empty-sequence() { let $entry := {$message} return update insert $entry into doc($log-file)/* }; + +declare function fontaneSimple:make-img($node as element(tei:figure), $uri as xs:string, +$log as xs:string, $flag as xs:string?) as element(tei:figure) { + let $display := + if($node/ancestor::tei:zone[@type = "illustration"]/tei:milestone[@unit = "illustration"][. << $node]) then + "block" + else + "inline" + let $img-url := try {tbleapi:get-url($uri, $node/@xml:id, "png") } + catch * { fontaneSimple:add-log-entry($log, "No TBLE-file found for " || $node/@xml:id) } + let $img-url := + if($display = "inline") then + replace($img-url, ",1000", ",500") + else + $img-url + let $rotation := + (: comment right after element:) + if($node/following-sibling::node()[1][self::comment()][matches(./string(), "rotate")]) then + substring-after($node/following::comment()[1], "rotate(") + => substring-before("deg") + (: comment as first descendant :) + else if($node/child::node()[1][self::comment()][matches(./string(), "rotate")]) then + substring-after($node/child::comment()[1], "rotate(") + => substring-before("deg") + else + () + + return + element tei:figure { + $node/@*, + attribute href {$img-url}, + if($flag = "double") then + (attribute type {"double"}, + attribute id {util:hash(generate-id($node), "md5")}) + else + (), + if($rotation) then + attribute rotate {$rotation} + else + (), + fontaneSimple:transform($node/node(), $uri, $log) + } +}; + + +declare function fontaneSimple:make-double-img($node as element(tei:figure), +$uri as xs:string, $log as xs:string) as element(tei:figure)+ { + let $left-img-part := fontaneSimple:make-img($node, $uri, $log, "double") + let $right-img-part := fontaneSimple:make-right-img-part($node, $uri, $log) + + return + ($left-img-part, + $right-img-part) +}; + +declare function fontaneSimple:make-right-img-part($node as element(tei:figure), +$uri as xs:string, $log as xs:string) as element(tei:figure) { + let $next-id := $node/ancestor::tei:surface/@next + => replace("#", "") + let $corresp-node := $node/root()//tei:surface[@xml:id = $next-id]//tei:figure + + return + fontaneSimple:make-img($corresp-node, $uri, $log, "double") +}; + +declare function fontaneSimple:make-pb($node as element(tei:surface)) as element(tei:pb)? { + let $editorial-list-entries := $node/root()//tei:msContents/tei:ab/tei:list[@type="editorial"]//tei:ref + let $refs := for $entry in $editorial-list-entries return + $entry/@target/string() + => substring-after("@n='") + => substring-before("']") + let $refs := distinct-values($refs) + return + if($node/@n = $refs) then + element tei:pb { + attribute n {$node/@n} + } + else + () +}; diff --git a/modules/fontane/edited-text/teisimplehelpers.xqm b/modules/fontane/edited-text/teisimplehelpers.xqm index 3ab419197d6425cc609b3deab6c7f03f2d95ebb6..b44c662d5cc32cbcdc4392aa9e4001552d094d14 100644 --- a/modules/fontane/edited-text/teisimplehelpers.xqm +++ b/modules/fontane/edited-text/teisimplehelpers.xqm @@ -84,10 +84,21 @@ declare function simpleHelpers:prepare-text($node as text()) as text()? { (: and $node/parent::tei:add) then:) (: $node:) (: else :) - if(ends-with($node, "-") and not(simpleHelpers:keep-hyphen($node))) then - text {functx:substring-before-last($node, "-") || "@P"} - else if(ends-with($node, "⸗") and not(simpleHelpers:keep-hyphen($node))) then - text {functx:substring-before-last($node, "⸗") || "@P"} + if(ends-with($node, "-") + and + ($node/ancestor::tei:line//text()[not(normalize-space(.) = "")][last()] = $node + or $node/ancestor::tei:rs[@next]//text()[last()] = $node + or $node/ancestor::*/following-sibling::tei:milestone[@unit = "line"]) + and not(simpleHelpers:keep-hyphen($node))) then + text {functx:substring-before-last($node, "-") || "@P"} + + else if(ends-with($node, "⸗") + and + ($node/ancestor::tei:line//text()[not(normalize-space(.) = "")][last()] = $node + or $node/ancestor::tei:rs[@next]//text()[last()] = $node + or $node/ancestor::*/following-sibling::tei:milestone[@unit = "line"]) + and not(simpleHelpers:keep-hyphen($node))) then + text {functx:substring-before-last($node, "⸗") || "@P"} else replace($node, "⸗", "-") let $save-whitespaces := replace($cleared-end-hyphen, " ", "@@") @@ -103,7 +114,8 @@ declare function simpleHelpers:prepare-text($node as text()) as text()? { else $cleared-round-s let $escaped-big-space := text{replace($cleared-big-space, " ", "?@?")} - let $cleared-Tironian := replace($cleared-big-space, "⁊c.", "etc.") + let $escaped-dito := text{replace($escaped-big-space, "〃", "?@@?")} + let $cleared-Tironian := replace($escaped-dito, "⁊c.", "etc.") return (: in cases where a given $node only consists of a hyphen we don't return a text node because it's unnecessary and leads to problems @@ -298,8 +310,8 @@ declare function simpleHelpers:is-hand-valid($hands as xs:string*, $node as element(tei:milestone)) as xs:boolean { let $current-hand := replace($node/@subtype, "#", "") return - if(functx:is-value-in-sequence($current-hand, $hands) - or ($node/ancestor::*[@type = ("label", "toc", "Kalenderblatt")] + if($node/root()//tei:handNote[@xml:id = $current-hand]/@script = "contemporary" + or ($node/ancestor::*[@type = ("label", "toc")] and matches($current-hand, "Friedrich_Fontane")) ) then true() @@ -382,17 +394,6 @@ as xs:boolean { false() }; - -(: TODO :) -(:declare function simpleHelpers:make-section($node as element(tei:milestone)) -as element(tei:section) { - let $id := substring-after($node/@spanTo, "#") - let $corresp := $node/following::*[$id = @xml:id] - let $bla := console:log(util:get-fragment-between($node, $corresp, true(), true())) - return -
-};:) - declare function simpleHelpers:find-chars($node as element(tei:lb)) as node()* { let $prev-line := $node/preceding::tei:line[1] let $prev-last-text := $prev-line/text()[last()] diff --git a/modules/fontane/edited-text/tests/presort-test-runner.xq b/modules/fontane/edited-text/tests/presort-test-runner.xq deleted file mode 100644 index 6de684f0afdb1df3e95ed2f4b06a6111751b760a..0000000000000000000000000000000000000000 --- a/modules/fontane/edited-text/tests/presort-test-runner.xq +++ /dev/null @@ -1,12 +0,0 @@ -xquery version "3.1"; - -(: This main module starts the tests stored in teisimple-test.xql. :) - -import module namespace presort-test = "http://fontane-nb.dariah.eu/presort-test" at "presort-test.xq"; -import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; - -declare namespace tei="http://www.tei-c.org/ns/1.0"; - -test:suite( - util:list-functions("http://fontane-nb.dariah.eu/presort-test") -) diff --git a/modules/fontane/edited-text/tests/presort-test.xq b/modules/fontane/edited-text/tests/presort-test.xq deleted file mode 100644 index 3210580c0b4237006549a41b6eea612c023889d1..0000000000000000000000000000000000000000 --- a/modules/fontane/edited-text/tests/presort-test.xq +++ /dev/null @@ -1,76 +0,0 @@ -xquery version "3.1"; - -(: This library module contains XQSuite tests for the presorting module stored - : in ../presort.xqm :) - -module namespace presort-test = "http://fontane-nb.dariah.eu/presort-test"; - -import module namespace presort="http://fontane-nb.dariah.eu/presort" at "../presort.xqm"; - -declare namespace tei="http://www.tei-c.org/ns/1.0"; -declare namespace test="http://exist-db.org/xquery/xqsuite"; - - -(: Text :) -declare - %test:name("Text nodes") - %test:args("Just some text") - %test:assertEquals("Just some text") - - %test:args("Text with Ümläöuts") - %test:assertEquals("Text with Ümläöuts") - - %test:args("Hiſtoriſches ✓") - %test:assertEquals("Hiſtoriſches ✓") - function presort-test:text($node as text()) { - presort:sort($node) -}; - -(: Default nodes :) -declare - %test:name("Default nodes") - %test:args("") - %test:assertEquals("") - - %test:args("STAATSBIBLIOTHEK •BERLIN•") - %test:assertEquals("STAATSBIBLIOTHEK •BERLIN•") - function presort-test:default-nodes($node as element(*)) { - presort:sort($node) -}; - - -(: @next nodes :) -declare - %test:name("Establishing right order with @next nodes") - (: case 1: two elements referencing each other also stand right next to each - other, i.e. there's no text inbetween. then nothing should happen :) - %test:args("in das Auguſtinerkloſterzu Erfurt") - %test:assertEquals("in das Auguſtinerkloſterzu Erfurt") - - (: case 2: two elements referencing each other are seperated by an arbitrary - amout of text. then they should be sorted into the right order :) - %test:args("2. Luther, Eisleben1483Some TextEin Stück ſeines Mantels und ſei") - %test:assertEquals("2. Luther, Eisleben1483Ein Stück ſeines Mantels und ſeiSome Text") - - function presort-test:next-nodes($node as element(*)) { - presort:sort($node) -}; - - -(: @prev nodes :) -declare - %test:name("Omit @prev nodes") - %test:args("") - %test:assertEquals("") - - %test:args("STAATSBIBLIOTHEK •BERLIN•") - %test:assertEquals("STAATSBIBLIOTHEK •BERLIN•") - - %test:args("STAATSBIBLIOTHEK •BERLIN•") - %test:assertEquals("STAATSBIBLIOTHEK •BERLIN•") - - %test:args("STAATSBIBLIOTHEK •BERLIN•") - %test:assertEquals("STAATSBIBLIOTHEK •BERLIN•") - function presort-test:omit-prev-nodes($node as element(*)) { - presort:sort($node) -}; diff --git a/modules/fontane/edited-text/tidysimple.xqm b/modules/fontane/edited-text/tidysimple.xqm index b0bb4e3a394229ef86b1edbfb5052e0078aeb8cb..fe982709f8b8252223274a1a5ea2c511eedbb679 100644 --- a/modules/fontane/edited-text/tidysimple.xqm +++ b/modules/fontane/edited-text/tidysimple.xqm @@ -20,7 +20,6 @@ declare namespace test="http://exist-db.org/xquery/xqsuite"; import module namespace config="http://textgrid.de/ns/SADE/config" at "../../config/config.xqm"; import module namespace functx="http://www.functx.com"; import module namespace index-info="http://fontane-nb.dariah.eu/index-info" at "index-info.xqm"; -import module namespace presort="http://fontane-nb.dariah.eu/presort" at "presort.xqm"; import module namespace simpleHelpers="http://fontane-nb.dariah.eu/teisimplehelpers" at "teisimplehelpers.xqm"; @@ -31,19 +30,24 @@ declare variable $tidySimple:valid-hands := declare function tidySimple:main($tei as node()*, $uri as xs:string) { - let $tidy := tidySimple:enhance-handshifts($tei//tei:text) +(: let $tidy := tidySimple:enhance-handshifts($tei//tei:text):) + let $tidy := tidySimple:enhance-handshifts($tei) => tidySimple:sort-out-surplus-elements() => tidySimple:sort-out-invalid-hands() => tidySimple:split-headings() => tidySimple:summarize() -(: => tidySimple:summarize-hi():) + => tidySimple:summarize-headings() + => tidySimple:summarize-notes() + => tidySimple:summarize-hi() + => tidySimple:sort-double-imgs() + => tidySimple:tidy() let $header := tidySimple:get-Fontanes-sources($tei//tei:teiHeader[parent::tei:TEI]) => tidySimple:get-references-in-abstract() let $id-parts := tokenize($tei//tei:TEI/@id, " ") let $key1 := substring($id-parts[2], 1, 1) let $key2 := substring($id-parts[2], 2) - let $final-tei := {$header}{$tidy} + let $final-tei := {$header}{$tidy//tei:text} let $store := xmldb:store($config:data-root || "/print/xml/", $uri || ".xml", $final-tei) return $final-tei @@ -90,7 +94,8 @@ as node()* { calendar pages by Friedrich Fontane. Unfortunately, Friedrich's handshift is oftentimes not the first hand appearing on the page but we want to keep the page nevertheless. :) - if($node/@type = "Kalenderblatt") then + if($node/@type = "Kalenderblatt" + or $node/@type = "clipping") then tidySimple:copy-element($node, "post") else tidySimple:invalid-hands-default-return($node) @@ -136,8 +141,8 @@ as node()* { case element(tei:milestone) return if($node/@unit = "handshift") then - if(simpleHelpers:is-prev-hand-same($node) - or not(tidySimple:has-hand-text($node))) then + if( + simpleHelpers:is-prev-hand-same($node)) then () else element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { @@ -145,6 +150,11 @@ as node()* { tidySimple:sort-out-surplus-elements($node/node()) } + else if($node/@unit = "line" + and ($node/ancestor::tei:seg[@type = "missing-hyphen"] + or $node/preceding-sibling::*[1][self::tei:seg[@type = "missing-hyphen"]])) then + () + else element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { $node/@*, @@ -269,10 +279,18 @@ declare function tidySimple:copy-element($node as node(), $flag as xs:string) tidySimple:get-Fontanes-sources($node/node()) else if($flag = "summarize") then tidySimple:summarize($node/node()) + else if($flag = "summarize-headings") then + tidySimple:summarize-headings($node/node()) + else if($flag = "summarize-notes") then + tidySimple:summarize-notes($node/node()) else if($flag = "summarize-hi") then tidySimple:summarize-hi($node/node()) else if($flag = "ref") then tidySimple:get-references-in-abstract($node/node()) + else if($flag = "double-imgs") then + tidySimple:sort-double-imgs($node/node()) + else if($flag = "tidy") then + tidySimple:tidy($node/node()) else text{"!!!Kopieren des Elements fehlgeschlagen!!!"} } @@ -390,41 +408,25 @@ declare function tidySimple:split-headings($nodes as node()*) as node()* { default return element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { $node/@*, - if($node/tei:add[@type = "edited_text" and @subtype = "interlinear"]) then - let $add := $node/tei:add[@type = "edited_text" and @subtype = "interlinear"] - return - (element tei:seg{ - attribute type {"upper-part"}, - $add/node() - }, - element tei:lb{ - attribute type {"edited_text"} - }, - element tei:seg{ - attribute type {"lower-part"}, - $add/following-sibling::node() - }) - else +(: if($node/tei:add[@type = "edited_text" and @subtype = "interlinear"]) then:) +(: let $add := $node/tei:add[@type = "edited_text" and @subtype = "interlinear"]:) +(: return:) +(: (element tei:seg{:) +(: attribute type {"upper-part"},:) +(: $add/node():) +(: },:) +(: element tei:lb{:) +(: attribute type {"edited_text"}:) +(: },:) +(: element tei:seg{:) +(: attribute type {"lower-part"},:) +(: $add/following-sibling::node():) +(: }):) +(: else:) tidySimple:split-headings($node/node()) } }; - -declare function tidySimple:get-next-content($node as node()*, $content as node()*) -as node()* { - if($node/@next) then - let $next-hi-id := substring-after($node/@next, "#") - let $next-node := $node/following-sibling::*[@xml:id = $next-hi-id] - let $next-content := $next-node//text()[not(ancestor::tei:index)] - let $break := if($node/@break = "true") then text{" "} else () - let $content := ($content, $break, $next-content) - - return - tidySimple:get-next-content($next-node, $content) - else - $content -}; - declare function tidySimple:get-Fontanes-sources($header as node()*) { for $node in $header return typeswitch ($node) @@ -485,71 +487,182 @@ declare function tidySimple:summarize($nodes as node()*) as node()* { case element(tei:rs) return tidySimple:summarize-entries($node) - case element(tei:list) return + case element(tei:div) return tidySimple:summarize-entries($node) +(: case element(tei:list) return:) +(: tidySimple:summarize-entries($node):) + case element(tei:item) return tidySimple:summarize-entries($node) -(: case element(tei:hi) return:) -(: tidySimple:summarize-entries($node):) - case element(tei:seg) return + if($node/following-sibling::*[1][self::tei:lb[@type = "edited_text"]] + or $node/following-sibling::*[2][self::tei:lb[@type = "edited_text"]] + or $node/preceding-sibling::*[1][self::tei:lb[@type = "edited_text"]] + or $node/preceding-sibling::*[2][self::tei:lb[@type = "edited_text"]]) then + tidySimple:copy-element($node, "summarize") + else + tidySimple:summarize-entries($node) + + case element(tei:table) return + tidySimple:summarize-entries($node) + + case element(tei:note) return tidySimple:summarize-entries($node) default return - tidySimple:copy-element($node, "summarize") + if(not($node/descendant::*[self::tei:milestone[@unit = "line"]]) + or not($node/descendant::*[self::tei:rs][@prev or @next]) + or not($node/descendant::*[self::tei:list][@prev or @next]) + or not($node/descendant::*[self::tei:item][@prev or @next]) + or not($node/descendant::*[self::tei:seg][@prev or @next]) + or not($node/descendant::*[self::tei:table][@prev or @next])) then + tidySimple:copy-element($node, "summarize") + else + $node }; declare function tidySimple:summarize-entries($node as node()) as node()* { (: the first element of a virtual aggregation:) - if($node/@next and not($node/@prev)) then - element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { - $node/(@* except @next), - tidySimple:apply-all-nexts($node) - } + if(($node/@next and not($node/@prev)) + or ($node/@next and $node/@prev and $node/ancestor::tei:seg[@type = "integration"]) + or ($node/@next and $node/@prev and tidySimple:find-corresp-node($node, "prev")[self::tei:ab[@type = "sketch"] or self::tei:anchor or self::tei:head])) then + let $next-node := tidySimple:find-corresp-node($node, "next") + let $prev-node := + if($node/@prev) then + tidySimple:find-corresp-node($node, "prev") + else + () + + return + if($next-node[self::tei:ab] + or $next-node[self::tei:seg[@type = "integration"]] + or $next-node[self::tei:ab[@type = "sketch"]] + or $next-node[ancestor-or-self::tei:seg[@type = "integration"]][not(local-name(.) = ("rs", "item", "seg"))] + or $next-node[descendant::tei:seg[@type = "integration"]][not(local-name(.) = ("rs", "item", "seg"))] + or not(local-name($node) = local-name($next-node)) + ) then + tidySimple:copy-element($node, "summarize") + else if($prev-node/ancestor::tei:seg[@type = "integration"]) then + () + else + element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + $node/(@* except @next), + tidySimple:apply-all-nexts($node, "summarize") + } else if($node/@prev) then - () + let $prev-node := tidySimple:find-corresp-node($node, "prev") + return + (: in some cases we have elements that have been part of a virtual aggregation + but their preceding aggregation element is lost, e.g. in case of a + tei:line pointing to a tei:zone. since we don't keep lines, this + link is lost, but we still want to keep that zone. :) + if($prev-node[@type = "vertical-mark"] and not($node[@type = "vertical-mark"]) + or not(local-name($node) = local-name($prev-node))) then + tidySimple:copy-element($node, "summarize") + else if($prev-node) then + () + else + tidySimple:copy-element($node, "summarize") + (: nodes that aren't part of the virtual aggregation :) else tidySimple:copy-element($node, "summarize") }; -declare function tidySimple:apply-all-nexts($node as node()) as node()* { +declare function tidySimple:apply-all-nexts($node as node(), $flag as xs:string) +as node()* { (: entry point of virtual aggregation:) if($node/@next and not($node/@prev)) then let $next-node := tidySimple:find-corresp-node($node, "next") - let $nodes-inbetween := $node/following::node()[. << $next-node] + let $nodes-inbetween := $node/following-sibling::node()[. << $next-node] + let $nodes-inbetween := ($nodes-inbetween, $node/following::node()[. << $next-node][self::tei:milestone]) + let $is-next-node-nested := + if($nodes-inbetween/descendant::* = $next-node) then + true() + else + false() return if(count($next-node) = 1) then - (tidySimple:summarize($node/node()), - $nodes-inbetween, - tidySimple:apply-all-nexts($next-node)) + ( + if($flag = "hi") then + tidySimple:summarize-hi($node/node()) + else + tidySimple:summarize($node/node()), + $nodes-inbetween, + if($is-next-node-nested) then + () + else + tidySimple:apply-all-nexts($next-node, $flag) + ) else - () + if($flag = "hi") then + tidySimple:summarize-hi($node/node()) + else + tidySimple:summarize($node/node()) (: last of a virtual aggregation: exit point :) else if(not($node/@next)) then - tidySimple:summarize($node/node()) + if($flag = "hi") then + tidySimple:summarize-hi($node/node()) + else + tidySimple:summarize($node/node()) (: element in the middle of a virtual aggregation:) else let $next-node := tidySimple:find-corresp-node($node, "next") - let $nodes-inbetween := $node/following::node()[. << $next-node] + let $nodes-inbetween := $node/following-sibling::node()[. << $next-node] + let $nodes-inbetween := ($nodes-inbetween, $node/following::node()[. << $next-node][self::tei:milestone]) + let $is-next-node-nested := + if($nodes-inbetween/descendant::* = $next-node) then + true() + else + () return if(count($next-node) = 1) then - (tidySimple:summarize($node/node()), - $nodes-inbetween, - tidySimple:apply-all-nexts($next-node)) + ( + if($flag = "hi") then + tidySimple:summarize-hi($node/node()) + else + tidySimple:summarize($node/node()), + $nodes-inbetween, + if($is-next-node-nested) then + () + else + tidySimple:apply-all-nexts($next-node, $flag) + ) else - () + if($flag = "hi") then + tidySimple:summarize-hi($node/node()) + else + tidySimple:summarize($node/node()) }; +declare function tidySimple:exclude-nested-hi($nodes as node()*, $hi-to-exclude as element(tei:hi)) as node()* { + for $node in $nodes return + typeswitch ($node) + case text() return + $node + + case comment() return + $node + + default return + if($node = $hi-to-exclude) then + () + else + element {QName("http://www.tei-c.org/ns/1.0", $node/name())} { + $node/@*, + tidySimple:exclude-nested-hi($node/node(), $hi-to-exclude) + } +}; + declare function tidySimple:find-corresp-node($node as node(), $flag as xs:string) { let $target-id := if($flag = "next") then @@ -559,7 +672,7 @@ declare function tidySimple:find-corresp-node($node as node(), $flag as xs:strin else error(QName("FONTANE", "tidySimple001"), "Invalid flag: " || $flag || "." ) return - $node/root()//*[@xml:id = $target-id] + $node/root()//*[@xml:id = $target-id][1] }; @@ -600,7 +713,70 @@ declare function tidySimple:get-references-in-abstract($nodes as node()*) as nod tidySimple:copy-element($node, "ref") }; -declare function tidySimple:summarize-hi($nodes as node()*) as node()* { + +declare function tidySimple:sort-double-imgs($nodes as node()*) as node()* { + for $node in $nodes return + typeswitch ($node) + + case text() return + $node + + case comment() return + $node + + case element(tei:ab) return + if($node//tei:figure[@type = "double"]) then + if($node/@next) then + let $next-id := $node/@next + => replace("#", "") + let $corresp-node := $node/root()//*[@xml:id= $next-id] + return + ($node, $corresp-node) + else + () + else + tidySimple:copy-element($node, "double-imgs") + + default return + tidySimple:copy-element($node, "double-imgs") +}; + + +declare function tidySimple:summarize-headings($nodes as node()*) as node()* { + for $node in $nodes return + typeswitch ($node) + + case text() return + $node + + case comment() return + $node + + case element(tei:head) return + if($node/@next) then + let $next-id := tidySimple:get-id($node/@next) + let $corresp-node := tidySimple:find-corresp-node($node, "next") + + return + if($corresp-node[self::tei:seg]) then + element tei:head { + $node/@*, + $node/node() + } + else + $node + else if($node/@prev) then + () + else + tidySimple:copy-element($node, "summarize-headings") + + default return + tidySimple:copy-element($node, "summarize-headings") +}; + + +(:~ A function for summarizing tei:note, especially for authorial notes :) +declare function tidySimple:summarize-notes($nodes as node()*) as node()* { for $node in $nodes return typeswitch ($node) @@ -610,54 +786,188 @@ declare function tidySimple:summarize-hi($nodes as node()*) as node()* { case comment() return $node + case element(tei:note) return + if($node/@next) then + let $next-id := tidySimple:get-id($node/@next) + let $corresp-node := tidySimple:find-corresp-node($node, "next") + + return + element tei:note { + $node/(@* except @next), + $node/node(), + $corresp-node/node() + } + else if($node/@prev) then + () + else + tidySimple:copy-element($node, "summarize-notes") + + default return + tidySimple:copy-element($node, "summarize-notes") +}; + + +(:~ A function for summarizing tei:hi :) +declare function tidySimple:summarize-hi($nodes as node()*) as node()* { + for $node in $nodes return + typeswitch ($node) + + case text() return + (: this should avoid duplicates :) + if($node/ancestor::tei:rs + and $node/preceding-sibling::*[self::tei:hi[@next]] + and $node/preceding-sibling::*[self::tei:hi[@next]]/following-sibling::text()[1] = $node) then + () + else + $node + + case comment() return + $node + case element(tei:hi) return - tidySimple:summarize-entries($node) + (: first element of virtual aggregation :) + if($node/@next and not($node/@prev)) then + let $next := tidySimple:find-corresp-node($node, "next") + let $nodes-inbetween := $node/following::*[. << $next] + return + if($nodes-inbetween[self::tei:milestone[@unit = "paragraph"]] + or $next/ancestor::* = $node + or not(local-name($next) = "hi")) then + tidySimple:copy-element($node, "summarize-hi") + else + element tei:hi { + $node/(@* except @next), + tidySimple:apply-all-nexts($node, "hi") + } + (: middle or last element o virutal aggregation:) + else if($node/@prev) then + if(tidySimple:find-corresp-node($node, "prev") = $node/ancestor::*) then + () + else + let $prev := tidySimple:find-corresp-node($node, "prev") + let $nodes-inbetween := $node/preceding::*[. >> $prev] + return + if($nodes-inbetween[self::tei:milestone[@unit = "paragraph"]] + or not(local-name($node) = local-name($prev))) then + tidySimple:copy-element($node, "summarize-hi") + else + () + (: not part of virtual aggregation at all :) + else + tidySimple:copy-element($node, "summarize-hi") default return tidySimple:copy-element($node, "summarize-hi") }; -declare function tidySimple:summarize-hi-entries($node as node()) as node()* { - (: the first element of a virtual aggregation:) - if($node/@next and not($node/@prev)) then - element tei:hi { - $node/(@* except @next), - tidySimple:apply-all-hi-nexts($node) - } - else if($node/@prev) then - () - (: nodes that aren't part of the virtual aggregation :) - else - tidySimple:copy-element($node, "summarize-hi") -}; +declare function tidySimple:tidy($nodes as node()*) as node()* { + for $node in $nodes return + typeswitch ($node) + + case text() return + if(normalize-space($node) = "") then + if( + ($node/preceding::*[1][self::tei:milestone] + and $node/following::*[1][self::tei:milestone]) + ) then + () + else + tidySimple:fix-text($node) + + else if(ends-with($node, "- ") + and $node/following::*[1][self::tei:milestone[@unit = "line"]]) then + let $fixed := + tidySimple:fix-text($node) + => functx:right-trim() + return + text{$fixed} + + else if(ends-with($node, "@P ") + and $node/following::*[1][self::tei:milestone[@unit = "line"]]) then + let $fixed := + tidySimple:fix-text($node) + => functx:right-trim() + return + text{$fixed} -declare function tidySimple:apply-all-hi-nexts($node as node()) as node()* { - (: entry point of virtual aggregation:) - if($node/@next and not($node/@prev)) then - let $next-node := tidySimple:find-corresp-node($node, "next") - let $nodes-inbetween := $node/following::node()[. << $next-node] - return - if(count($next-node) = 1) then - (tidySimple:summarize-hi($node/node()), - $nodes-inbetween, - tidySimple:apply-all-hi-nexts($next-node)) else + tidySimple:fix-text($node) + + case element(tei:milestone) return + if($node[@unit = "line"]) then + if(($node/following::node()[1][self::tei:milestone[@unit = "line"]] + or normalize-space($node/following::node()[1]) = "") + and $node/following::*[1][self::tei:milestone[@unit = "line"]]) then + () + else + $node + else if($node[@unit = "line"] + and $node/following::node()[1][self::tei:milestone[@unit = "handshift"]]) then () + else + $node - (: last of a virtual aggregation: exit point :) - else if(not($node/@next)) then - tidySimple:summarize-hi($node/node()) + case element(tei:figure) return + if($node/ancestor::tei:ab) then + tidySimple:copy-element($node, "tidy") + else + () - (: element in the middle of a virtual aggregation:) - else - let $next-node := tidySimple:find-corresp-node($node, "next") - let $nodes-inbetween := $node/following::node()[. << $next-node] - return - if(count($next-node) = 1) then - (tidySimple:summarize-hi($node/node()), - $nodes-inbetween, - tidySimple:apply-all-hi-nexts($next-node)) + case element(tei:seg) return + if($node[@type = "verse"] and not($node//text())) then + () + else if($node[@type = "integration"] and count($node/*) = 2) then + () + else if($node//* or $node//node()) then + tidySimple:copy-element($node, "tidy") + else + () + + case element(tei:div) return + if($node//text()[not(normalize-space(.) = "")]) then + tidySimple:copy-element($node, "tidy") + else + () + + case element(tei:list) return + if($node//text()[not(normalize-space(.) = "")]) then + tidySimple:copy-element($node, "tidy") else () + + + default return + tidySimple:copy-element($node, "tidy") +}; + +declare function tidySimple:fix-text($node as text()) as text() { + let $special-chars := "\.,\)\?\-!" + let $string := + replace($node, " \-", "-") + => replace("@P ", "@P") + => replace("\[@@", "[") + => replace(" \)", ")") + => replace(" ;", ";") + let $string := + if(ends-with($string, "@@")) then + let $next-char := substring($node/following::text()[1], 1, 1) + return if(matches($next-char, $special-chars)) then + substring($string, 1, string-length($string) - 2) + else + $string + else + $string + let $string := + if(normalize-space($string) = "") then + let $next-char := substring($node/following::text()[1], 1, 1) + return if(matches($next-char, $special-chars)) then + substring($string, 1, string-length($string) - 2) + else + $string + else + $string + + return + text{$string} };