= XML Workflow = [[PageOutline(2-4,,pullout)]] Auf dieser Seite wird der XML-Workflow für die Umwandlung eines [wiki:despecs DESpecs]-konformen Rohtextes in einen [wiki:echo-schema Schema]-konformen XML-Text beschrieben. (Anmerkungen zu den einzelnen Schritten sind [wiki:workflow-notes hier].) Bisher sind mehr als 50 schemakonforme Texte bei ECHO, siehe [http://mpdl-proto.mpiwg-berlin.mpg.de/mpdl/attribute-query-result.xql?docbase=echo&query-type=browse&order-by=author&pn=1 hier]. Bis auf [http://mpdl-proto.mpiwg-berlin.mpg.de/mpdl/page-query-result.xql?document=/echo/la/Alvarus_1509.xml Alvarus], [http://mpdl-proto.mpiwg-berlin.mpg.de/mpdl/page-query-result.xql?document=/echo/la/Benedetti_1585.xml Benedetti 1585] und [http://mpdl-proto.mpiwg-berlin.mpg.de/mpdl/page-query-result.xql?document=/echo/zh/SongYingxing_1637.xml Song Yingxing] sind alle Texte mit den hier beschriebenen Workflow-Skripten erzeugt worden. Der Text [source:trunk/texts/WO_5/Zonca_1656/raw/Zonca_1656_UR271U6Y.txt Zonca 1656] ist ein Beispiel für einen problemlos zu konvertierenden Text. == Die Arbeitsschritte == Der XML-Workflow besteht aus mehreren Arbeitsschritten. Im [#a1.Vorbereitungen ersten Schritt] werden alle Vorbereitungen getroffen, um mit dem raw text arbeiten zu können. Im [#a2.rawtextbearbeiten zweiten Schritt] wird der raw text annotiert und korrigiert. Im [#a3.Schrittebiszuwohlgeformtemxml dritten Schritt] wird der annotierte raw text in wohlgeformtes XML verwandelt. Im [#a4.schema-konformmachen vierten Schritt] wird der XML-Text schemakonform gemacht. Der dritte und der vierte Schritt laufen weitgehend automatisch ab. Die Arbeitsschritte bestehen jeweils aus einer [source:trunk/schema/scripts/workflow Reihe von Skripten]. Einige dieser Skripte sind noch nicht ganz auf ihre Beschreibung auf dieser Seite abgestimmt oder sind noch leere Platzhalter, aber die Workflow-Struktur ist bereits recht ausgereift. === Textfilter === Die Skripte sind Textfilter in !TextWrangler bzw. BBEdit. Textflter haben eine ganze Text-Datei oder auch nur ein Textstück als input. !TextWrangler ersetzt das Textstück dann durch den output des Textfilters. Ein Textfilter ist also eine Art erweiterte !Suchen/Ersetzen-Funktion. Insbesondere Skripte mit Parametern wie das -Skript (Schritt 5.01) probiert man normalerweise erst an einzelnen Textstellen aus, bevor man es für den ganzen Text verwendet. Andere Skripte wie zum Beispiel das Skript in Schritt 3.05 kann man nicht sinnvoll auf Textstücke, sondern nur auf den gesamten Text anwenden. Wenn ein Skript einen Fehler findet, der es am Weiterarbeiten hindert, gibt das Skript eine Fehlermeldung aus. !TextWrangler ändert dann nicht die Datei, sondern gibt die Fehlermeldung in einem getrennten Fenster aus. Nur wenn ein Skript ohne Fehlermeldung durchläuft, verändert es den Text. Skripte, die mit `find`, `check` oder `test` beginnen, verändern den Text nie, sondern geben immer nur „Fehlermeldungen“ aus. Die Skripte können auch von der command line gestartet werden. Der Dateiname wird dann als Parameter übergeben, und die Ausgabe ist in ''stdout'', Fehlermeldungen dagegen in ''stderr''. Die Meta-Skripte in Schritt 3 und 4 rufen die anderen Skripte als Unix-pipe über die command line auf. Die Anwendung in !TextWrangler ist allerdings bequemer. === 1. Vorbereitungen === In diesem Schritt werden alle Vorbereitungen getroffen, um mit dem raw text arbeiten zu können. Insbesondere werden Verzeichnisse angelegt und Dateien kopiert. ==== 1.01 Von Pythia ins svn-repository ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_1_01_import_text.pl Filter_1_01_import_text] legt die Verzeichnisse im repository an und kopiert den Text von Pythia in das repository. * Im [source:trunk/texts Texte-Verzeichnis] Unterverzeichnisse anlegen * Datei aus Pythia rüberkopieren * Kopie erstellen und umbenennen (`autor_jahr_identifier`), Zeilenenden von CRLF zu LF. Entferne [http://de.wikipedia.org/wiki/Byte_Order_Mark BOM]-Fragmente (korrekte BOMs sind okay). Im Gegensatz zu den weiteren Skripten ist zumindest das Skript in Schritt 1.01 kein Text-Filter, denn man arbeitet hier noch gar nicht mit einem Text-Editor. ==== 1.02 Kommunikation mit Foxridge ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_1_02_import_metadata.pl Filter_1_01_import_metadata] kommuniziert mit Foxridge. Das Skript setzt voraus, dass der achtstellige Identifier im Dateinamen steht. (Das Skript wird daher nicht mit Archimedes-legacy-Verzeichnissen funktionieren.) Erstelle eine lokale Kopie der entsprechenden index.meta-Datei: {{{ http://content.mpiwg-berlin.mpg.de/mpiwg/online/permanent/library/2UZM8E2N/index.meta }}} Extrahiere daraus die Metadaten und schreibe sie in den `metadata`-Block (siehe [#a2.rawtextbearbeiten Schritt 2]) in den raw text. Die Metadaten werden wörtlich übernommen, das Format wird erst in Schritt [#a2.01Metadaten 2.01] angepasst. Übernommen werden (jeweils in /): * `` * `` * `<year>` * `<lang>` ([http://de.wikipedia.org/wiki/ISO_639 ISO 639-1], d.h. zweistellig) * (bisher noch nicht: `<publisher>`, `<city>`, `<number_of_pages>`, `<translator>`) Finde den pageimg-Unterordner (default ist `pageimg/`) und schreibe die JPG-Dateinamen unbearbeitet in den `pageimg`-Block (siehe [#a2.rawtextbearbeiten Schritt 2]) in den raw text. Änderungen in index.meta: * index.meta neu formatieren. * Wenn <texttool> noch nicht vorhanden ist, anlegen. * Pageimg und figures anlegen, aber unverändert lassen, wenn es sie schon gibt. * text-url-path anlegen: Sprache aus z.B. `<lang>it</lang>`. === 2. raw text bearbeiten === In diesem Arbeitsschritt wird der raw text auf die Umwandlung in XML vorbereitet. Das erste Skript bearbeitet den `metadata`-Block, den [source:trunk/schema/scripts/workflow/Filter_1_02_import_metadata.pl Filter_1_01_import_metadata] im raw text angelegt hat. Das zweite Skript löst den `pageimg`-Block auf und verteilt den Inhalt auf die <pb> im Text. Alle weiteren Skripte verändern den raw text gar nicht, sondern finden Stellen, die per Hand geändert werden müssen. Am Anfang der Datei sind folgende Blöcke erlaubt: * `metadata:` (kopiert aus `index.meta` in Schritt 1.02, korrigiert in Schritt 2.01, aufgelöst in Schritt 3.05) * `pageimg:` (kopiert aus `pageimg/` in Schritt 1.02, aufgelöst bereits in Schritt 2.02) * `unknown:` (angelegt in Schritt 2.04, aufgelöst in Schritt 3.01) * `replacements:` (angelegt per Hand; könnte man noch aufteilen in forbidden characters aus Schritt 2.03, escape sequences aus Schritt 2.05, special instructions aus Schritt 2.10; aber bringt das mehr Klarheit? Aufgelöst in Schritt 3.02) * `parameters:` (per Hand angelegt, immer wenn es nötig ist; Beispiel `reg.additionalWordlist = URL`. Aufgelöst in Schritt 3.05, wo es in <echo:parameters> umgewandelt wird.) * `log:` (per Hand angelegt, immer wenn es nötig ist. Aufgelöst in Schritt 3.05, wo es in <dcterms:description> umgewandelt wird.) Jeden Block kann es höchstens einmal geben. Alle Blöcke sind vor dem ersten `<pb>` (d.h. vor dem eigentlichen Text). Die Blöcke werden jeweils durch eine Leerzeile voneinander getrennt. Die Reihenfolge der Blöcke ist beliebig, allerdings ist die oben angegebene Reihenfolge die präferierte Reihenfolge. Änderungen am raw text werden soweit wie möglich mit Hilfe dieser Blöcke gemacht. Nur wenn es nicht anders geht, wird der Text selbst geändert. Der Sinn der Aufteilung in Anlegen der Blöcke in Schritt 1 und 2 und Auflösen der Blöcke in Schritt 3 ist, dass man möglichst lange mit dem raw text arbeiten kann. Es soll außerdem möglichst einfach nachvollziehbar bleiben, welche Änderungen an der aus China erhaltenen Version gemacht wurden, ohne dass beispielsweise durch das Einfügen von <s> jede Zeile anders aussieht als in der originalen Transkription. Erst in Schritt 5 wird die XML-Version des Textes ein Faktum an sich, das nicht mehr jederzeit neu aus dem raw text erzeugt werden kann. Idealerweise fällt das mit dem Beginn des scholarly workflow zusammen. Es ist möglich, bereits im raw text korrektes XML zu verwenden, ohne dass die Skripte darüber stolpern. Beispielsweise kann man bereits jetzt `<div type="body">` einfügen. Ein anderes Beispiel: Während der Bearbeitung fällt auf, dass ein Abschnitt auf italienisch ist. Dies kann mit `<p xml:lang="it">` markiert werden. Die Skripte ignorieren tags, die bereits wohlgeformte Attribute enthalten. ==== 2.01 Metadaten ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_01_additional_metadata.pl Filter_2_01_additional_metadata] bearbeitet die in Schritt 1.02 aus `index.meta` in den `metadata`-Block kopierten Metadaten. Es verwendet die Hilfsdatei `metadata-GND.txt`. Für die Metadaten wird eine Kurzschreibweise verwendet, die nicht XML ist. Bei Personen wird, falls bekannt, die GND eingefügt. Beispiel: {{{ metadata: dcterms:creator (GND:118859676) Benedetti, Giovanni Battista de }}} Unbekannte Personen werden von dem Skript in die GND-Datei eingetragen. Diese Datei kann mehrere Einträge für dieselbe Person haben, nämlich einen Eintrag für jede bei uns vorkommende Schreibweise. Für die unbekannte Person muss die GND per Hand im Text und in der GND-Datei nachgetragen werden. Eventuell wird auch ein link eingefügt, mit dem man die GND prüfen kann, zum Beispiel [http://d-nb.info/gnd/118859676] für Benedetti. (Irgendwann könnte das durch ein interaktives tool passieren.) Außerdem fügt das Skript links zu ECHO ein, beispielsweise {{{ http://echo.mpiwg-berlin.mpg.de/ECHOdocuView/ECHOzogiLib?mode=imagepath&url=/mpiwg/online/permanent/library/163127KK/pageimg http://mpdl-proto.mpiwg-berlin.mpg.de/mpdl/page-query-result.xql?document=/echo/la/Benedetti_1585.xml http://echotest.mpiwg-berlin.mpg.de/content/historymechanics/Echo/163127KK }}} Der erste link ist für die weitere Bearbeitung besonders wichtig, denn die beiden anderen links funktionieren erst, wenn der Text nach der Bearbeitung als XML-Text hochgeladen wird. Am Ende müssen die Metadaten per Hand geprüft werden. ==== 2.02 pb's synchronisieren ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_02_sync_pb.pl Filter_2_02_sync_pb] nimmt die JPG-Dateinamen aus dem `pageimg`-Block und schreibt sie hinter die <pb> im Text. Die Zuordnung muss dann per Hand geprüft werden. Falls die Zuordnung nicht stimmt, müssen die Dateinamen im `pageimg`-Block umsortiert und/oder <pb> im Text ergänzt werden (zu viele <pb> im Text sind selten). Danach muss das Skript wiederholt werden. (Beachte, dass man in diesem Schritt keine weiteren Textänderungen machen sollte, da sie durch das Rückgängigmachen wieder verschwinden.) Da die Zuordnung der Textseiten zu den JPGs Voraussetzung für das Arbeiten mit dem Text ist, wird der `pageimg`-Block im Gegensatz zu den anderen Blöcken bereits hier aufgelöst. Das Skript macht also Änderungen im ganzen Dokument, zum Beispiel: {{{ original: <pb 25><rh>_running head_</rh> in 2.02: <pb 25>[0037]<rh>_running head_</rh> }}} Später wird daraus: {{{ in 3.04: <pb 25>[0037]<rh><it>running head</it></rh> in 3.06: <pb o="25"/>[0037]<rh><it>running head</it></rh> in 4.01: <pb o="25" file="0037" n="37" rhead="running head"/> }}} Bei Dateinamen ohne `.jpg` im `pageimg`-Block, wie zum Beispiel `.DS_Store`, bricht das Skript mit einer Fehlermeldung ab. Wenn ein <pb> im Text fehlt, ist es manchmal sehr zeitraubend herauszufinden, wo genau es fehlt. Für diesen Schritt gibt es daher ein Helfer-Skript [source:trunk/schema/scripts/workflow/Filter_2_02_check_pb.pl Filter_2_02_check_pb], das von jeder Seite die ersten Zeilen anzeigt und den offset zwischen der Nummer im JPG-Dateinamen und der Seitenzahl im Buch berechnet. Wenn der offset längere Zeit kostant bleibt und sich dann ändert, deutet das darauf hin, dass an dieser Stelle im Text ein <pb> fehlt. (Eine andere mögliche Ursache ist eine fehlerhafte Paginierung im Buch.) ==== 2.03 ersetze verbotene Zeichen im Text ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_03_find_forbidden_characters.pl Filter_2_03_find_forbidden_characters] erstellt eine Liste verbotener Zeichen und Uncode-Blöcke im Text, bei einzelnen Zeichen mit Korrekturvorschlag. Beispiele: * ɩ („latin small letter iota“) aus dem Unicode-Block „IPA Extension“ anstelle von „dotless i“. Der ganze Block „IPA Extension“ ist verboten, aber bei den anderen Zeichen gibt es keinen automatischen Korrekturvorschlag. * Beispiel aus einem chinesischen Text: ○ (white circle U+25CB) statt 〇 (ideographic number zero U+3007) * ÿ statt ij in kursivem Text (Beispiel für ein sprachabhängiges Zeichen: Zum Beispiel im Französischen kann ÿ [http://de.wikipedia.org/wiki/Ÿ vorkommen].) * „substitute“ (U+001A): kommt in manchen Text ganz am Ende vor und scheint ein Artefakt der Umwandlung des intern verwendeten doc-Formats zu txt bei Formax zu sein. * zwei spaces hintereinander * Zeichen, die in den Skripten intern verwendet werden: ¤, ¥. (Diese Währungszeichen als reservierte Zeichen wurden ausgewählt, weil sie in alten Texten wahrscheinlich nicht vorkommen, aber in vielen modernen Fonts verfügbar sind. Eine Alternative wären Zeichen aus dem oben ausgeschlossenen IPA-Block.) Soweit wie möglich sollten die Korrekturen im `replacements`-Block am Anfang des Textes stehen. Der `replacements`-Block wird in Schritt 3.02 aufgelöst. Einzelfälle können aber auch direkt im Text korrigiert werden. Beispiel: Ein einzelnes `Hinɔ` wird zu `Hinc`. Das Skript verwendet als default die Hilfsdatei [source:trunk/texts/aux/forbidden-characters.txt forbidden-characters.txt]. ==== 2.04 prüfe unknown characters ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_04_check_unknown_characters.pl Filter_2_04_check_unknown_characters] sammelt die im Text verwendeten Codes der Form `<001>`, listet jeweils das erste Vorkommen im Text auf und schlägt jeweils passende Ersetzungen vor (die default-Hilfsdatei ist [source:trunk/texts/aux/unknown-euro2.txt unknown-euro2.txt]). Das Skript macht zwar einen Vorschlag für `unknown`-Block, schreibt ihn aber nicht selbst in den Text, denn ein Skript, das in stderr schreibt, soll nicht gleichzeitig den Text verändern. Der Benutzer muss den Block also von stderr in den Text kopieren. Die Vorschläge müssen dann per Hand geprüft werden. Beispiel: {{{ unknown: <002> = ꝑ <006> = ℞ ℟ ꝶ ? (recipe, response, -rum) }}} wird zu {{{ unknown: <002> = ꝑ (p.28: ok) <006> = ℞ (used as a variable name) }}} ==== 2.05 prüfe escape sequences ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_05_check_escape_sequences.pl Filter_2_05_check_escape_sequences] ruft intern erst die Skripte 3.01, 3.02 und 3.03 auf und prüft dann, ob danach noch folgende Zeichen im Text sind: 1. { 1. \ Man muss dann bei jeder Fundstelle entscheiden, ob diese geschweiften Klammern etc. legitimerweise noch im Text sind oder ob das Skript in Schritt 3.03 nicht korrekt arbeitet. Beispiel: Im Text wird die idiosynkratische Notation {ta} für eine Ligatur in kursiver Schrift verwendet: {{{ replacements: {ta} ta (vorläufig!) }}} Einzelne Stellen können auch im Text selbst korrigiert werden. ==== 2.06 prüfe italics ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_06_check_underscores.pl Filter_2_06_check_underscores] prüft, ob es Schwierigkeiten bei der Umwandlung der Kurzschreibweise `_ _` für italics geben wird. Die Probleme werden dann von Hand korrigiert. In Schritt 3.04 werden die `_ _` dann in <it> verwandelt. Die Umwandlung erfolgt also, bevor die <s> in den Text eingefügt werden. Die Umwandlung von <it> in die endgültige Form <emph style="it"> findet dagegen erst nach dem Einfügen der <s> statt. ==== 2.07 prüfe tags ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_07_check_tags.pl Filter_2_07_check_tags] prüft ein paar Fälle, die nicht vorkommen sollten und auf Fehler bei der Transkription hindeuten. Der Sinn dieser Prüfung ist auch, dass sich die weiteren Skripte auf die Einhaltung dieser formalen Dinge verlassen können. Beispiele: * `<h>`, `<mgl>`, `<mgr>` jeweils am Anfang einer Zeile * `</h>`, `</mgl>`, `</mgr>` jeweils am Ende einer Zeile * `<tb>`, `<fig>` auf eigener Zeile * bei `<pb>` ist nur noch `<rh>` in der gleichen Zeile erlaubt * nicht-existente Elemente, wie z.B. in `<scG</sc>`, oder auch `<sup>9</sup>` statt `<^>9</^>` (aber siehe unten) * verschachtelte `<p>` (vermutlich ein `<p>` zuviel), und entsprechend für `<h>` etc. * `</p>` ohne vorhergehendes `<p>`, und entsprechend für `<h>` etc. * zusammengehörende Tags wie `<p>` und `</p>` liegen sehr weit auseinander * zusammengehörende Tags wie `<rh>` und `</rh>` sind nicht in der gleichen Zeile Wie bei Schritt 2.03 muss man jeweils entscheiden, ob eine Korrektur im Text selbst gemacht wird oder in den `replacements`-Block geschrieben wird. Beispiel: {{{ replacements: << « (lines 41 to 43) }}} Bei den Dingen, die in diesem Schritt geprüft werden, kann man unterscheiden in echte Fehler, die das Skript nicht korrigieren kann, und falsche Formatierungen, die das Skript selbst korrigieren könnte. Beispielsweise könnte das Skript selbst ein return einfügen, wenn <tb> nicht auf einer eigenen Zeile steht. Aber zum Beispiel gibt es in den DESpecs die Regel, dass eine heading <h> auf eigener Zeile stehen muss, ein running head <rh> dagegen auf der gleichen Zeile wie das zugehörige <pb>. Wenn dies nicht beachtet wurde, ist meistens nicht klar gewesen, ob eine Textzeile eine Überschrift oder ein running head ist. Damit hier keine Information verschwindet, verändert das Skript den Text nicht selbst. Das Skript ignoriert alles vor dem ersten <pb>. Für dieses Skript gibt es einen [source:trunk/schema/scripts/script-tests/check_tags-testparcours.txt testparcours]. ==== 2.08 prüfe <s> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_08_check_s.pl Filter_2_08_check_s] soll prüfen, ob beim Einfügen von <s> in Schritt 4.04 etwas schiefgehen wird. Zum Beispiel: * verdächtig kurze <s> * Zeichen, die normalerweise nicht am Anfang von <s> stehen sollten: {{{ Drei Punkte ... sind keine Satzpunkte. (Beachte Klammern.) <s>Drei Punkte .</s><s>.. sind keine Satzpunkte. </s><s>(Beachte Klammern.</s><s>)</s> }}} ==== 2.09 prüfe tables ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_2_09_check_tables.pl Filter_2_09_check_tables] prüft die "syntaktische Korrektheit" und die Plausibilität der tables. Was das genau bedeutet, ist noch nicht ganz klar. (Es wird jedenfalls nicht geprüft, ob die Tabelle das Original korrekt wiedergibt.) Es ist auch noch nicht ganz klar, wie eventuelle Korrekturen in den raw text geschrieben werden, d.h. ob sie in der Syntax der DESpecs hineingeschrieben werden oder schon als xhtml. Wenn als xhtml, muss es von den folgenden Skripten ignoriert werden. In jedem Fall muss es in Schritt 4.02 aus dem Absatz herausgezogen werden. ==== 2.10 Special Instructions ==== Für einzelne Texte oder Work Orders kann es Skripte der Form [source:trunk/schema/scripts/workflow/Filter_2_10_special_instructions_for_xxxxxxxx Filter_2_10_special_instructions_for_xxxxxxxx] geben. Bei manchen Texten mit Special Instructions wird es einfacher sein, die nötigen Anpassungen statt mit einem Skript per Hand zu machen. Beispiel [wiki:WO2_Barrow_1674 Barrow 1674]: {{{ replacements: --] < (i.e. "--]" becomes "<"; see p.0018 and "DESpecs_special_batch3.pdf") [-- > }}} Zum Beispiel die Special Instructions für die Tabellen am Ende von [wiki:WO4_Berzelius_1819 Berzelius 1819] würden dagegen eher mit einem Skript weiterverarbeitet werden. === 3. Schritte bis zu wohlgeformtem xml === Diese Skripte in diesem Arbeitsschritt sollten problemlos durchlaufen und können daher in einem Meta-Skript [source:trunk/schema/scripts/workflow/Filter_3_make_wellformed.pl Filter_3_make_wellformed] zusammengefasst werden. Das Skript [source:trunk/schema/scripts/workflow/Filter_3_test_wellformedness.pl Filter_3_test_wellformedness] prüft anschließend, ob das Ergebnis wohlgeformt ist. Wichtig: Sobald der Text wohlgeformtes XML ist, sollte man ihn mit Dateiendung `.xml` statt `.txt` (im Verzeichnis `xml` statt `raw`) abspeichern. ==== 3.01 ersetze unknown characters ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_3_01_replace_unknown_characters.pl Filter_3_01_replace_unknown_characters] ersetzt die Zeichen aus der default-Hilfsdatei [source:trunk/texts/aux/unknown-euro2.txt unknown-euro2.txt] und dem `unknown`-Block. Der `unknown`-Block wird dabei entfernt. Das Skript zur Ersetzung der escape sequences (Schritt 3.03) kann sich darauf verlassen, dass die unknown characters bereits geändert wurden. Das ist wichtig für Fälle wie `\'<001>`. ==== 3.02 ersetze replacements ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_3_02_replace_replacements.pl Filter_3_02_replace_replacements] ersetzt die Zeichen aus dem `replacements`-Block, beispielsweise das {{{ replacements: << « (lines 41 to 43) }}} aus Schritt 2.07. Auch hier kann sich das Skript für die escape sequences drauf verlassen, dass diese Ersetzungen bereits durchgeführt wurden. ==== 3.03 ersetze escape sequences ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_3_03_replace_escape_sequences.pl Filter_3_03_replace_escape_sequences], das in Schritt 2.05 vorbereitet wurde, löst alle escape sequences auf, sowie einige weitere Schreibweisen aus den DESpecs: * Sequenzen mit \ wie `\'q` etc. * `$` wird zu `ſ` ([http://de.wikipedia.org/wiki/Langes_s long s]) * löse `{ }` auf: `{ij}` auf zu `ij`, `{ae}` zu `ę` Anschließend wird der Text in Unicode-Normalform [http://unicode.org/reports/tr15/ NRC] gebracht. Alle folgenden Skripte können sich darauf verlassen, den Text in NRC-Normalform vorzufinden. Wichtig wird dies in Schritt 5. Das Skript soll nicht mitdenken, sondern einfach die Schreibweisen der DESpecs in Unicode umsetzen: * `\-` wird hier zu einem combining macron, weil es so im transkribierten Text steht. Später wird das in den meisten Fällen zu einer Tilde korrigiert, weil das Makron normalerweise eine falsche Transkription einer Tilde ist. * Genauso ist `\,e` in den meisten Fällen in Wirklichkeit `ę`, wird aber hier zu `ȩ`. * Zeichen, die wir absichtlich nicht in die Specs aufgenommen haben, zum Beispiel `<^>9</^>` für ꝰ (modifier letter us, U+A770), werden hier ebenfalls noch nicht umgewandelt. (Wenn aber zum Beispiel in der Transkription subscript und superscript verwechselt wurden und das in Schritt 2 auffällt, kann man dort `<_>9</_> ꝰ` in den `replacements`-Block schreiben.) * `{ij}` wird zwar hier zu `ij`, aber in einem späteren Schritt wird `ij` stillschweigend wieder zu `ij` (ohne `{ }`). * Für die Ligatur `{is}` in italics gibt es gar kein Ligatur-Zeichen in Unicode, sodass es gleich stillschweigend durch `is` ersetzt wird. Eine Lösung wie `i ZWJ j` mit dem Zero Width Joiner (U+200D) funktioniert leider nur in der [http://www.unicode.org/versions/Unicode5.2.0/ch16.pdf Theorie] (dort p.506). ==== 3.04 ersetze italics ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_3_04_replace_underscores.pl Filter_3_04_replace_underscores] ersetzt die Kurzschreibweise `_ _` für italics durch `<it> </it>` (siehe Schritt 2.06). Diese Ersetzung ist nicht Teil des emph-Skriptes, weil sie vor <s> passieren sollte. Alle `_` vor dem ersten `<pb>` werden ignoriert. ==== 3.05 Metadaten, root element ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_3_05_add_basic_xml.pl Filter_3_05_add_basic_xml] ergänzt die XML-Präambel `<?xml version="1.0" encoding="UTF-8"?>` und fügt das root element `<echo>` sowie `<metadata>` und `<text type="free">` ein. Der Text im `log`-Block wird zu `<log>`. Genauso wird der Text im `parameters`-Block zu (einem einzigen) `<parameters>`. Alle nachfolgenden Skripte finden daher ihre Parameter nicht mehr im `parameters`-Block, sondern in `<parameters>`. ==== 3.06 wohlgeformtes xml ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_3_06_make_tags_wellformed.pl Filter_3_06_make_tags_wellformed] macht die tags wohlgeformt: * reservierte Zeichen in XML: `&` wird zu `&`. (Das Skript kann mehrere Male aufgerufen werden, es wird also aus `&` nicht `&amp;`.) Die verbotenen Zeichen < und > wurden bereits in Schritt 2.07 abgefangen. * Attribute: `<... it>` wird zu `<... style="it">`, genauso für `fr`. Das Skript ignoriert tags, die bereits Attribute mit der gültigen Syntax `name="wert"` haben. * ergänze „`/`“ in den ungeschlossenen Elementen wie `<pb>` und `<hd>` * korrigiere verbotene Element-Namen wie `<^>` Das Skript ändert außerdem soweit wie möglich die Element-Namen der DESpecs bereits in ihre Gegenstücke im ECHO Schema. Die tags, die später zu <emph> werden, werden hier nicht umbenannt. === 4. schema-konform machen === Wie in Schritt 3 sollten diese Skripte problemlos durchlaufen und können daher in einem Meta-Skript [source:trunk/schema/scripts/workflow/Filter_4_make_valid.pl Filter_4_make_valid] zusammengefasst werden. Das Skript [source:trunk/schema/scripts/workflow/Filter_4_test_validity.pl Filter_4_test_validity] test dann, ob das Ergebnis schemakonform ist. (Dieses Skript ist ein Wrapper für Jing, das die eigentliche Validierung macht.) ==== 4.01 <pb> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_4_01_pb.pl Filter_4_01_pb] verwandelt `<rh>` in ein Attribut `rhead` in `<pb>`. Alle Formatierungen wie kursiv, gesperrt, Fettdruck etc. im running head werden entfernt, weil es recht sicher ist, dass sie semantisch irrelevant sind. Die grundsätzliche Frage, wie genau wir die originale Textgestalt wiedergeben wollen, selbst wenn sie offensichtlich semantisch nicht relevant ist, haben wir allerdings noch nicht genau geklärt. ==== 4.02 floats herausziehen ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_4_02_move_floats.pl Filter_4_02_move_floats] zieht Floats aus Absätzen heraus: An der ursprünglichen Stelle wird `<anchor>` eingefügt, und alle Floats eines Absatzes kommen in ein `<div type="float">` direkt nach dem Absatz. Dadurch bleiben die Floats im Text in der richtigen Reihenfolge. Das Kriterium in den DESpecs, wo die Floats zu tippen sind, ist recht krude. Daher ist eine minimale Nachbereitung sinnvoll. Zum Beispiel wird ein Float stillschweigend aus dem Absatz geschoben, wenn nur eine einzige Textzeile davor oder danach ist. (Als Folge können allerdings Marginalien, die sich auf einen Absatz beziehen, im xml formal vor oder nach dem Absatz stehen.) Da dies automatisch geschehen kann, wird es nicht schon in Schritt 2 gemacht. ==== 4.03 <lb> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_4_03_insert_lb.pl Filter_4_03_insert_lb] verwandelt Zeilenumbrüche in <lb/>. Als Effekt des Skriptes wird die Zeilenanzahl des Textes sehr viel kleiner. ==== 4.04 <s> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_4_04_insert_s.pl Filter_4_04_insert_s] fügt <s> ein. Bei diesem Skript kann man bestimmte Parameter wählen, um bessere <s> zu erhalten. Trotzdem kann es manchmal passieren, dass man zum raw text zurückkehren muss und dort bei manchen Punkten manuell markieren muss, ob es eine Satzende ist oder nicht. Das können einzelne Punkte sein, wo es sich wahrscheinlich nur in Ausnahmefällen lohnen wird, oder wiederkehrende Situationen wie eine nicht erkannte Abkürzung. ==== 4.05 <emph> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_4_05_emph.pl Filter_4_05_emph] ersetze Fomatierungs-tags durch `<emph style="...">`. Vorher verwandelt das Skript small caps: {{{ V<sc>ORNAME</sc> N<sc>ACHNAME</sc> <sc>Vorname Nachname</sc> }}} Verschiebe style-Informationen außerdem so wie wie möglich nach oben im xml: {{{ <p><emph style="it">text</emph>.</p> <p style="it">text.</p> }}} Anderes Beispiel: {{{ original: <mgl>_Eine kur-_<lb/>_ze Notiz._</mgl> in 3.04: <mgl><it>Eine kur-</it><lb/><it>ze Notiz.</it></mgl> in 4.02: <note position="left" xml:space="preserve"><it>Eine kur-</it><lb/><it>ze Notiz.</it></note> in 4.05: <note position="left" style="it" xml:space="preserve">Eine kur-<lb/>ze Notiz.</note> }}} Für dieses Skript gibt es einen [source:trunk/schema/scripts/script-tests/emph-testparcours.txt testparcours]. ==== 4.06 tables ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_4_06_tables.pl Filter_4_06_tables], das in Schritt 2.09 vorbereitet wurde, verwandelt die Tabellen-Syntax der DESpecs in gültiges xhtml. Wie schon in Schritt 2.09 wird auch hier nicht geprüft, ob die Tabelle tatsächlich dem Original nahekommt. Dies passiert erst im scholarly workflow. ==== 4.07 <div> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_4_07_insert_div.pl Filter_4_07_insert_div] fügt eine simple <div>-Struktur in den Text ein, indem es bei jeder <head>-Gruppe ein <div> beginnen lässt. Dadurch bekommt der Text ein rudimentäres Inhaltsverzeichnis. Eine Beschreibung, wie man die entstandene flache <div>-Struktur in eine hierarchische <div>-Struktur verwandelt, ist [wiki:div hier]. ==== 4.08 Formatieren ==== Wenn der Text schemakonform ist, kann man ihn neu formatieren. Es müssen keine Zeilen umgebrochen werden, sondern nur die Anzahl der Leerzeichen am Anfang normalisiert werden. === 5. Textanalyse === Hier gibt es einen Einschnitt im workflow: Der schemakonforme xml-Text wird bearbeitet. Es ist dann nicht mehr möglich, einfach zum raw text zurückzukehren und alle Bearbeitungsschritte noch einmal zu machen. Dies fällt, wie schon in Schritt 2 gesagt, idealerweise mit dem Beginn des (automatiserbaren Teils des) scholarly workflow zusammen. Die Nummern dieser Skripte in diesem Schritt können sich noch ändern. ==== 5.01 <reg> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_5_01_insert_reg.pl Filter_5_01_insert_reg] regularisiert den Text. Für eine ausführlichere Diskussion von <reg> siehe [wiki:regularisierung hier]. Wie beim <s>-Skript kann man hier einige Parameter wählen. Die Details der Parameter stehen noch nicht fest. Das Skript verwendet Hilfsdateien wie `reg-wordlist-lat.txt` und `reg-abbreviations-ger.txt`. Eventuell gehen die Hilfsdateien auch über reine Wortlisten hinaus. Beispielsweise könnte es möglich sein, einzelne Abkürzungen mit etwas wie `add abbr z.B.` hinzuzunehmen und mit `ignore abbr z.B.` aus der Standard-Liste zu streichen. Kein Zeichen, das normalisiert werden soll, darf hinterher noch im Text (außerhalb von `<reg>`) sein, zum Beispiel kein Zeichen mit Tilde (mit Ausnahmen in manchen Sprachen). Für !Latein/Benedetti: * Zeichen mit Tilde: ã ẽ ĩ õ ũ ñ * combining tilde, insbesondere p̃ t̃ q̃ r̃ (viele Fonts zeigen solche combining characters nicht über, sondern neben dem Zeichen an; dann muss der User einen Font wähen, der sich besser an die Unicode-Vorgaben hält) * combining acute, insbesondere q́ * medievalist characters: ꝑ ꝓ ꝗ ꝗ̃ ꝙ ꝰ  ́ ꝯ (geeignete Fonts sind Andron, Junicode und Palemonas, die man [http://www.mufi.info/fonts/ hier] bekommt) * weitere: ę ĺ (das zweite Zeichen ist aus Alvarus) * Apostroph: in den Abschnitten in Benedetti mit `xml:lang="it"` bzw. `xml:lang="ita"` ist `'` dagegen erlaubt Für dieses Skript gibt es einen [source:trunk/schema/scripts/script-tests/reg-testparcours.txt testparcours]. Für diesen Schritt wäre ein interaktives tool besonders wichtig: Beispielsweise zeigt das Test-Skript Stellen an, wo noch unerwünschte Zeichen wie ę im Text stehen, der User ergänzt die Form, und sie wird automatisch im Text und in der entsprechenden Hilfsdatei nachgetragen. ==== 5.02 <var> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_5_02_insert_var.pl Filter_5_02_insert_var] fügt <var> um Variablen ein. Ein Ziel ist, den Inhalt vor der morphologischen Analyse zu verbergen. Eventuell hat dieses Skript ebenfalls Parameter, nämlich wie Variablen im Text aussehen (zum Beispiel „`AB`“ versus „`.a.b.`“). `<emph>` in Variablen wird wie bei running heads entfernt: Ob der Setzer ein K in upright shape oder in italics gewählt hat, ist egal. Für das Skript gibt es einen [source:trunk/schema/scripts/script-tests/var-testparcours.txt testparcours]. ==== 5.03 <num> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_5_03_insert_num.pl Filter_5_03_insert_num] fügt <num> um Zahlen ein, die nicht in der in modernen westlichen Texten üblichen Weise geschrieben sind. Ein Ziel ist wieder, den Inhalt vor der morphologischen Analyse zu verbergen. Beispiel: `<num value="0.5">½</num>`. ==== 5.04 Formeln ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_5_04_formulae.pl Filter_5_04_formulae] soll korrektes MathML erzeugen (oder zumindest korrektes TeX, das dann umgewandelt werden kann). Inwieweit das realistisch ist, weiß ich noch nicht. Zumindest bei einfachen Brüchen wie {5/8} sollte das jedoch möglich sein. ==== 5.05 <foreign> ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_5_05_insert_foreign.pl Filter_5_05_insert_foreign] soll fremdsprachliche Textstellen markieren. Füge zumindest für griechischen Text (erkennbar an den verwendeten Zeichen) `<foreign xml:lang="el">` ein. Durch eine minimale linguistische Analyse des Textes kann man auch weitere fremdsprachliche Textstücke korrekt erkennen. ==== 5.06 GIS ==== Füge GIS-Elemente in ausgewählte Texte ein, also in etwa `<person>`, `<place>`, `<time>`, `<event>`. Für eine ausführlichere Diskussion siehe [wiki:"2010-04-15 GIS meeting" hier]. ==== 5.07 Abgleich mit Donatus ==== In Zukunft soll die Textqualität durch linguistische Analysewerkzeuge verbessert werden (siehe auch Schritt 5.05). Einige Verbesserungen sind mit Hilfe von Donatus zumindest teilweise automatisierbar: * Einfügen fehlender Bindestriche * Korrektur von fehlenden/überflüssigen Spaces * korrigiere Standardfehler wie fumptis, fint, bumanitate in kursiv Es ist noch nicht ganz klar, wie man dabei zwischen Satzfehlern (mit <reg>) und Transkriptionsfehlern (ohne <reg>) unterscheiden kann. ==== 5.08 allgemeines Test-Skript ==== Brauchen wir ein allgemeines Test-Skript? Zum Beispiel kann es nach Anwenden eines Skriptes zwei Spaces hintereinander geben. Das muss kein Fehler des Skriptes sein, aber es deutet auf ein Problem hin. Ein möglicher Gesamt-Test für einen sorgfältig annotierten Text: Alle Punkte im Text gehören zu einer der folgenden Kategorien: * Satzende-Punkte (`<s>Bla bla bla. </s>`) * in einem Tag (`ex <ref>.7. quinti Eucl.</ref>`) * bei einer Zahl (`.11.`) === 6. weitere Skripte === ==== 6.01 div-Attribute ==== Das Skript [source:trunk/schema/scripts/workflow/Filter_5_06_number_divs.pl Filter_5_06_number_divs] numeriert die Attribute `<div level="." n=".">` korrekt durch. (Das Skript ist ein Wrapper für das XSLT-Skript `number-divs.xsl`, das die eigentliche Arbeit macht.) ==== 6.02 Nebenwirkungen von XSLT ausgleichen ==== Ein Skript, das nach Anwenden eines XSLT-Skripts das DTD-Fragment wieder einfügt und weitere Nebeneffekte von XSLT-Skripten rückgängig macht, insbesondere die Formatierung der Präambel. === 7. scholarly workflow === Einige Standard-Aufgaben des scholarly workflow, die teilweise bereits im Schema angelegt sind: * IDs einfügen (es könnte ein Modul geben, in dem das `id`-Attribut gefordert wird, und das mit der Zwiebelstruktur in diesem Stadium in Aktion tritt. Dann müssen wir nicht in den usage guide schreiben: Es ist zwar formal optional, aber es sollte verwendet werden.) * ersetze `<wrong/>` durch `<sic/>` oder entferne es; löse `<unsure/>` auf * weitere `<reg>`, Korrekturen von bestehenden `<reg>` * `<ref>` * weitere `<foreign>` * entferne library stamps * „old-style numerals typed as letters“, zum Beispiel `ex .II.` statt `ex .11.`, aber auch andersherum: `10. BENEDETTI` statt `IO. BENEDETTI` * Wörter mit einzelne griechischen oder einzelnen lateinischen Buchstaben (automatisierbar?) * Wörter mit einzelnen Großbuchstaben mitten im Wort (`ClaZomenius`). Häufig ist die Ursache ein fehlendes Space vor dem Großbuchstaben. Diese Aufgaben sollten durch interaktive tools unterstützt werden. === Anmerkungen === (siehe [wiki:workflow-notes#Anmerkungen workflow-notes]) == Besonderheiten bei chinesischen Texten == Version 2.1 der chinesischen DESpecs ist [http://pythia.mpiwg-berlin.mpg.de/department1/mpdl/despecs/DESpecs_chinese.pdf/DESpecs_chinese_V4.pdf hier]. * beachte die in [source:trunk/schema/schema/echo/modules/echo-chinese-text.rnc echo-chinese-text] definierten Attribute * andersherum sind einige Schritte für chinesische Texte unnötig, zumindest wenn der Text keine westlichen Textstücke enthält * lateinische Zeichen können durch ihre full-width-Version ersetzt sein, zum Beispiel im tag „<?>“ * Beispiel aus Schritt 2.03: ○ (white circle U+25CB) statt 〇 (ideographic number zero U+3007) * Wort- und Satzgrenzen markieren (bzw. andersrum: invisible spaces innerhalb von Wörtern entfernen) * Nach der Definition in Schritt 5.03 müsste man chinesische Zahlen in chinesischen Texten mit <num> markieren. Ist das tatsächlich sinnvoll? Es gibt jedenfalls ein älteres Skript für Euclid 1966, das beide Schreibweisen in westliche Zahlen umwandelt: {{{ <num value="301">三〇一</num> <num value="23">二十三</num> }}} === Zeichenvarianten === Wie der automatisierte Workflow für Zeichenvarianten aussehen wird, ist noch nicht völlig klar. Wenn zum Beispiel im Text <獘V> getippt wurde, kann man das automatisiert nur zu <reg norm="獘" type="V">獘</reg> mit vorläufigem Typ "V" machen, wo also das getippte Zeichen einfach wiederholt wird. Die Variante im Text kann dann nur eine studentische Hilfskraft anhand der von !ZhongYi erstellten Excel-Tabellen "herstellen". Ziel ist eine Zeichenfolge, die das Zeichen im Text beschreibt. Hier: ⿱敝大. Und dann: {{{ <reg norm="獘" type="simple"><image xlink:href="symbols/chinese/⿱敝大.svg"/></reg> }}} Wenn das Zeichen V,,1,, im Original eine Variante des Standardzeichens S ist, es aber in Unicode eine weitere Zeichenvariante V,,2,, von S gibt, die optisch näher an V,,1,, dran ist als S an V,,1,,, so sollen die Chinesen die Variante V,,2,, mit < V> tippen. Ein Beispiel ist <兾V> statt <冀V> in den [http://pythia.mpiwg-berlin.mpg.de/department1/mpdl/despecs/DESpecs_chinese.pdf/DESpecs_chinese_V4.pdf chinesischen DESpecs 2.1], p.10/11. Ziel ist dann: {{{ <reg norm="兾" type="simple"><image xlink:href="symbols/chinese/⿱𠂉異.svg"/></reg> }}} Das Herunterkochen von 兾 (V,,2,,) zu 冀 (S) sollte dann "von alleine" passieren. Allgemein: Was ist das Ziel, wenn die Chinesen eine Zeichenvariante (ohne < V>) getippt haben, die es in Unicode gibt? Soll die dann auch ein <reg> bekommen? Wer erkennt überhaupt, dass es sich um eine Variante handelt? Zumindest in der Theorie muss man das nicht regularisieren, und die Suche funktioniert von alleine richtig. Sollen wir umsteigen auf ein System, wo die Chinesen <001> tippen, und dann im Anhang eine IDS-Sequenz? Beispielsweise würde 国 durch die Unicode-Zeichenfolge ⿴口玉 beschrieben werden. == Andere Workflows == Wir erwarten, bald auch reinen Text ohne tags sowie Word-Texte in einem automatischen workflow in schemakonforme XML-Dokumente umwandeln zu können. Es muss sich noch zeigen, ob es praktischer ist, den Workflow anzupassen oder die unmarkierten Texte erst in ein DESpecs-konformes Zwischenformat zu bringen.