XML Workflow
Auf dieser Seite wird der XML-Workflow für die Umwandlung eines DESpecs-konformen Rohtextes in einen Schema-konformen XML-Text beschrieben. (Anmerkungen zu den einzelnen Schritten sind hier.)
Bisher sind mehr als 50 schemakonforme Texte bei ECHO, siehe hier. Bis auf Alvarus, Benedetti 1585 und Song Yingxing sind alle Texte mit den hier beschriebenen Workflow-Skripten erzeugt worden.
Der Text Zonca 1656 ist ein Beispiel für einen problemlos zu konvertierenden Text.
Die Arbeitsschritte
Der XML-Workflow besteht aus mehreren Arbeitsschritten. Im ersten Schritt werden alle Vorbereitungen getroffen, um mit dem raw text arbeiten zu können. Im zweiten Schritt wird der raw text annotiert und korrigiert. Im dritten Schritt wird der annotierte raw text in wohlgeformtes XML verwandelt. Im vierten Schritt wird der XML-Text schemakonform gemacht. Der dritte und der vierte Schritt laufen weitgehend automatisch ab.
Die Arbeitsschritte bestehen jeweils aus einer 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 <reg>-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 Filter_1_01_import_text legt die Verzeichnisse im repository an und kopiert den Text von Pythia in das repository.
- Im Texte-Verzeichnis Unterverzeichnisse anlegen
- Datei aus Pythia rüberkopieren
- Kopie erstellen und umbenennen (
autor_jahr_identifier
), Zeilenenden von CRLF zu LF. Entferne 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 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 Schritt 2) in den raw text. Die Metadaten werden wörtlich übernommen, das Format wird erst in Schritt 2.01 angepasst. Übernommen werden (jeweils in <resource>/<meta>):
<author>
<title>
<year>
<lang>
(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 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 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 ausindex.meta
in Schritt 1.02, korrigiert in Schritt 2.01, aufgelöst in Schritt 3.05)pageimg:
(kopiert auspageimg/
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; Beispielreg.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 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 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 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 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 ÿ 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 forbidden-characters.txt.
2.04 prüfe unknown characters
Das Skript 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 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 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:
- {
- \
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 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 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 testparcours.
2.08 prüfe <s>
Das Skript 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 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 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 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 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 Filter_3_make_wellformed zusammengefasst werden. Das Skript 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 Filter_3_01_replace_unknown_characters ersetzt die Zeichen aus der default-Hilfsdatei 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 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 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ſ
(long s)- löse
{ }
auf:{ij}
auf zuij
,{ae}
zuę
Anschließend wird der Text in Unicode-Normalform 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 denreplacements
-Block schreiben.) {ij}
wird zwar hier zuij
, aber in einem späteren Schritt wirdij
stillschweigend wieder zuij
(ohne{ }
).- Für die Ligatur
{is}
in italics gibt es gar kein Ligatur-Zeichen in Unicode, sodass es gleich stillschweigend durchis
ersetzt wird. Eine Lösung wiei ZWJ j
mit dem Zero Width Joiner (U+200D) funktioniert leider nur in der Theorie (dort p.506).
3.04 ersetze italics
Das Skript 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
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 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ürfr
. Das Skript ignoriert tags, die bereits Attribute mit der gültigen Syntaxname="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 Filter_4_make_valid zusammengefasst werden. Das Skript 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 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 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 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 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 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 testparcours.
4.06 tables
Das Skript 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 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 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 Filter_5_01_insert_reg regularisiert den Text. Für eine ausführlichere Diskussion von <reg> siehe 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 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 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 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 testparcours.
5.03 <num>
Das Skript 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 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 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 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 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.
stattex .11.
, aber auch andersherum:10. BENEDETTI
stattIO. 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 workflow-notes)
Besonderheiten bei chinesischen Texten
Version 2.1 der chinesischen DESpecs ist hier.
- beachte die in 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 V1 im Original eine Variante des Standardzeichens S ist, es aber in Unicode eine weitere Zeichenvariante V2 von S gibt, die optisch näher an V1 dran ist als S an V1, so sollen die Chinesen die Variante V2 mit < V> tippen. Ein Beispiel ist <兾V> statt <冀V> in den chinesischen DESpecs 2.1, p.10/11. Ziel ist dann:
<reg norm="兾" type="simple"><image xlink:href="symbols/chinese/⿱𠂉異.svg"/></reg>
Das Herunterkochen von 兾 (V2) 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.