Version 37 (modified by 14 years ago) (diff) | ,
---|
XML Workflow
Auf dieser Seite wird der XML-Workflow für die Umwandlung eines DESpecs-konformen Rohtextes in einen Schema-konformen XML-Text beschrieben.
Bisher sind 19 schemakonforme Texte bei ECHO, siehe mpdl-proto und echotest. Bis auf Alvarus, Benedetti 1585 und Song Yingxing sind alle Texte mit den hier beschriebenen Workflow-Skripten erzeugt worden.
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 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.
- Die Namen der Arbeitschritte sind nur guidelines. Beispielsweise sind die Teilschritte 3.03 (ersetze escape sequences) und 3.04 (ersetze italics) technisch gesehen nicht nötig für einen wohlgeformten Text und 4.07 (füge <div> ein) nicht nötig für einen schemakonformen Text, aber sie sind an den jeweiligen Stellen sinnvoll.
- Bei Skripten mit Parametern werden die Parameterwerte in den raw text eingetragen, und anpassbare Listen wie Wortabkürzungen werden aus Hilfsdateien eingelesen. Die Skripte selbst müssen daher nur selten angepasst werden.
- Im Gegensatz zu den früheren Skripten dürfen die hier beschriebenen Bearbeitungsschritte die Zeilenstruktur verändern, zum Beispiel eine Zeile hinzufügen.
- Beachte, dass Work Orders 1 bis 5 mit den DESpecs 1.1.2 und Work Orders 6 bis 9 mit den DESpecs 2.0 geschickt wurden. Unterschiede sind zum Beispiel das Format von Figures und von Tabellen.
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.
- Wenn wir einen transkribierten Text aus China erhalten, muss zuerst geprüft werden, ob die Datei tatsächlich, wie in den DESpecs verlangt, reiner Text in UTF-8 ist. Insbesondere akzeptieren wir keine doc-Dateien.
- Es ist noch nicht ganz klar, wo neue Dateien in Zukunft abgelegt werden: Kommen sie wie bisher zuerst nach Pythia oder gleich in das wiki-repository? Ich gehe vorläufig davon aus, dass Texte weiterhin zuerst nach Pythia kommen. Die Namenskonvention auf Pythia ist bisher
workorder_autor_jahr
.
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 (allerdings nerven die raw/xml-Verzeichnisse in der Praxis)
- Datei aus Pythia rüberkopieren
- Kopie erstellen und umbenennen (
autor_jahr_identifier
), Zeilenenden von CRLF zu LF. Entferne BOM-Fragmente (korrekte BOMs sind okay).
(Shell-Skript von Klaus)
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 (funktioniert nur innerhalb des Instituts):
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>
.
Das Skript meldet sich nicht bei Foxridge an. Die Änderungen in index.meta werden daher nur in der lokalen Kopie gemacht. Es fehlt also:
- Sicherheitskopie von index.meta anlegen (auch lokal?): Umbenennen von index.meta in index.meta.old, eine ältere Sicherheitskopie mit demselben Namen wird ohne Nachfrage überschrieben.
- Schreibe die neue index.meta
(Die Trennung der Schritte „Vorbereitung“ und „raw text bearbeiten“ wird nicht vollkommen eingehalten, denn dieses Skript schreibt bereits Daten in den raw text. Man könnte die Metadaten und JPG-Dateinamen auch erst in getrennte Dateien schreiben, aber ich wüsste nicht, was dadurch gewonnen wäre. Die Idee ist, dass alle textspezifischen Informationen in den Text geschrieben werden und alle allgemeinen Informationen wie die GND-Liste in Schritt 2.01 in getrennte Dateien.)
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)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. Vielleicht ersetze ich diese Kurzschreibweise aber auch wieder durch korrektes XML, sodass die Metadaten in Schritt 3.05 nur noch an die richtige Stelle kopiert werden müssen. Das XML aus index.meta muss allerdings auf alle Fälle an das Schema angepasst werden.
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 schreibt die JPG-Dateinamen im pageimg
-Block 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.)
Das Skript macht also Änderungen im ganzen Dokument, zum Beispiel:
<pb 25>[0037]
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.
Bei Dateinamen wie zzzz.jpg
und .DS_Store
im pageimg
-Block bricht das Skript mit einer Fehlermeldung ab.
Für diesen Schritt gibt es auch ein Helfer-Skript compare_pb_with_images.pl
, 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
.
Eventuell wird das Skript noch von einer Blacklist der verbotenenen Unicode-Blöcke auf eine Whitelist der erlaubten Unicode-Blöcke umgestellt. Vielleicht sollte man auch in den DESpecs eine Whitelist oder Blacklist vorgeben, um das zufällige Herauspicken von Unicode-Zeichen zu verhindern. Andererseits sind falsche Unicode-Zeichen leicht korrigierbar, solange sie konsistent verwendet werden.
2.04 prüfe unknown characters
Das Skript Filter_2_04_check_unknown_characters
sammelt die im Text verwendeten Codes der Form <001>
und schlägt jeweils passende Ersetzungen vor (aus einer Hilfsdatei). Diese Vorschläge müssen per Hand geprüft werden. Beispiel:
unknown: <002> ꝑ <006> ℞ (prescription take), ℟ (response), or ꝶ (rum)
wird zu
unknown: <002> ꝑ (p.28: ok) <006> ℞ (used as a variable name)
Eventuell sollte das Skript die codes auch schon in die Datei schreiben, damit man sie nicht rüberkopieren muss. Allerdings würde das Skript dann sowohl Textänderungen machen als auch eine Liste von Problemen anzeigen.
2.05 prüfe escape sequences
Das Skript Filter_2_05_check_escape_sequences ruft intern erst Filter_3_01_replace_unknown_characters auf und prüft dann, ob danach noch folgende Zeichen im Text sind: { und \
Man muss dann bei jeder Fundstelle entscheiden, ob diese geschweiften Klammern etc. legitimerweise noch im Text sind oder ob das Skript in Schritt 3.01 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.
Die Korrekturen in diesem Schritt werden wohl immer im Text selbst und nicht in den Blöcken vor dem Text gemacht.
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 könnte allerdings zumindest regexes vorschlagen, die der User verwenden kann. Langfristig sollte es eine interaktive Version dieses Schrittes geben.
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. <s>Drei Punkte .</s><s>.. sind keine Satzpunkte. </s>
(Kann man hier das s-Skript aufrufen, oder kommt man dann durcheinander, weil so viele Skripte dazwischen den Text verändern? Eventuell kann man hier diese Skripte gleich mit aufrufen. Ausgangspunkt ist jedenfalls das alte Skript Filter_4_04a_test_s.pl
.)
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") [-- >
(Schöner wäre es, wenn die entsprechende Zeichen durch Unicode-Mathematik-Zeichen angenähert werden könnten und die modernen Zeichen erst in der MathML-Formel verwendet werden. Leider gibt es diese Zeichen so nicht in Unicode. Der Umgang mit veralteter mathematischer Notation ist noch nicht vollständig geklärt. Alternative wäre wie bei Alchemie-Symbolen ein Bild; ist das bei Büchern mit vielen Formeln realistisch?)
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. (Dieses Skript ist zurzeit ein Wrapper für xmllint. Ich werde es wahrscheinlich noch auf ein Perl-Modul statt xmllint umstellen.)
Wenn der Text wohlgeformtes XML ist, sollte man ihn mit Dateiendung in xml
(im Verzeichnis xml/
statt raw/
) abspeichern.
3.01 ersetze unknown characters
Das Skript Filter_3_01_replace_unknown_characters ersetzt die Zeichen aus dem unknown
-Block. 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 (unglücklicher Name?) 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.
Dieser Schritt könnte mit Schritt 3.01 fusioniert werden. Ich sehe allerdings keine unmittelbare Notwendigkeit dafür.
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).
Beachte außerdem:
\'
(U+0027) kann im Text auch als\’
(U+2019) geschrieben sein (\'
wurde in den DESpecs leider als\’
geschrieben; Problem vonshortvrb
, mit dem beispielsweise§\'§
im XeLaTeX-Quellcode der DESPecs im fertigen PDF zu\’
wird, usw.)
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 <dcterms:description>
.
- Das Skript fügt auch ein DTD-Fragment ein, das den Text schemakonform macht, ohne dass man
xml:space="preserve"
in alle<s>
schreiben muss. Auf die Skript hat dies keinen Einfluss, aber es erleichtert das Bearbeiten des Textes in einem XML-Editor. Das Skript in Schritt 5.06, und allgemein jedes beliebige XSLT-Skript, löst als Nebeneffekt das DTD-Fragment wieder auf. Ein weiteres Skript wird das DTD-Fragment wieder einfügen können.
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. Insbesondere 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.)
Eine Ausnahme für das problemlose Durchlaufen kann das Skript für <s> sein.
Solange Tabellen noch nicht richtig verarbeitet werden (siehe Schritte 2.09 und 4.06), werden außerdem in Filter_4_00_Schummelskript Tabellen in <mgr> verwandelt, sodass sie korrekt aus dem Absatz herausgezogen werden.
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.
- Vorsicht bei anchored marginal notes.
- Prüfe bei anchors im Text, ob es eine zugehörige note auf der gleichen Seite gibt. Akzeptiere dabei kleine Abweichungen der Symbole voneinander, zum Beispiel
3)
im Text und3
in der Fußnote. Gib ansonsten eine Warnung aus. - Was passiert bei Floats in <h>, wenn sie nicht stillschweigend herausgeschoben werden können? Oder ist es besser, einen Fehler zu provozieren, weil solche <h> manchmal in Wirklichkeit <p type="title"> sind?
- Beachte Fußnoten auf zwei Seiten.
4.03 <lb>
Das Skript Filter_4_03_insert_lb verwandelt Zeilenumbrüche in <lb/>. Das ist normalerweise geradlinig. Beachte Ausnahmen bei <pb> und <anchor>. 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. Details und die Syntax dafür habe ich mir noch nicht überlegt.
Beachte Fälle wie:
- et.a.b.hoc est (hier normalisieren wir bisher die spaces, also „
et .a.b. hoc est
“) - .a.b:c.d:e.f.
- .
<lb/>
a.b. - Wort-Abkürzungen
&c.
etc.
Das Skript kann sich darauf verlassen, dass die Floats bereits aus dem Absatz herausgezogen sind. Dadurch wird das Markieren von <s> in Floats erleichtert. Das Skript kann sich aber nicht darauf verlassen, dass Wortabkürzungen bereits in <reg>
sind. Der Punkt am Ende von <reg>
zum Beispiel in ex .7. quinti <reg>Eucl.</reg>
wird außerdem oft noch als Satzendepunkt gebraucht.
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 (raw text und nach Schritt 3.04, 4.02 und 4.05):
<mgl>_Eine kur-_<lb/>_ze Notiz._</mgl> <mgl><it>Eine kur-</it><lb/><it>ze Notiz.</it></mgl> <note position="left" xml:space="preserve"><it>Eine kur-</it><lb/><it>ze Notiz.</it></note> <note position="left" style="it" xml:space="preserve">Eine kur-<lb/>ze Notiz.</note>
Beachte:
<_>
und<^>
wurden in Schritt 3.06 in<sub>
und<super>
umbenannt.- <it> in einem Absatz in italics ergibt wieder upright.
- Kombinationen wie
it bf
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.
Beachte die unterschiedlichen Anweisungen in den DESpecs 1.1.2 und 2.0.
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.
- Automatisch erstellte
<div>
sind alle auf demselben level. Für eine hierarchische <div>-Struktur (z.B. mit front, body, back) muss die automatische <div>-Struktur per Hand nachbearbeitet werden. n
undlevel
werden mitn="0"
undlevel="0"
gefüllt und erst im Schritt 5.06 korrekt durchnumeriert.- Korrigiere <div> (automatisch?) bei den
<head>
, die eigentlich Footer sind.
Es muss möglich sein, bereits im raw text <div type="body"> einzufügen (beachte: dann sollte auch der type in <text> geändert werden). Braucht man dazu ein tool, oder geht das so? Was ist die Verbindung zum <div>-Skript? Braucht man ein tool zur manuellen Nachbearbeitung der automatisch erstellten <div>?
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 scholarly workflow zusammen.
Die Nummern dieser Skripte in diesem Schritt können sich noch ändern. Die Hierarchie der inline-Elemente (z.B. <var> in plaintext, <ref> im inline model) legt vermutlich noch keine Verarbeitungsreihenfolge nahe.
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
.
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
Beachte:
- der modifier letter us ꝰ wird manchmal für
'
gehalten - Problem der Wort-Abkürzungen mit Kasus, zum Beispiel
ex .7. quinti Eucl.
. Verwende dort<ref>
, falls möglich.
Das Skript erwartet und hinterlässt den Text in NRC-Normalform. Escape sequences wie '
, die manche Text-Editor für '
verwenden, werden aufgelöst.
Für dieses Skript gibt es einen testparcours.
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>
.
(Verwende das Skript Filter_roman_numbers.pl
: <num value="..."> für römische Zahlen.)
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 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.)
5.07 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.08 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.09 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. 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
- Das Grundgerüst für die Skripte ist dieses template.
- Figures nachbearbeiten und ausschneiden: Sollte das ans Ende von Schritt 2? (und beachte DESpecs 1.1.2 versus 2.0)
- Wo werden sich überschneidende Hierarchien aufgelöst? Zum Beispiel Fußnoten, die auf der nächsten Seite weitergehen; Text flows mit getrennten Seitennumerierungen wie im Eipo-Text und den Conimbricenses; Absätze, die in einer column anfangen und in der nächsten column aufhören
- Das Skript zur Normalisierung der Interpunktion (Filter_punctuation.pl) habe ich vorläufig weggelassen, weil es vermutlich merkwürdige Nebenwirkungen hat. Zum Beispiel spaces vor „:“ weg. (Hier ist die Frage, ob wir Information verlieren, die wir gerne konservieren würden. Beispiel „EPISTOL AE“). Ziel ist wieder, dass sich die folgenden Skripte auf ein einheitliches Format verlassen können. Beispielsweise müsste das reg-Skript, das unter anderem
q;
durchque
ersetzt, nicht noch prüfen, ob esq ;
gibt.
- Filter_Archimedes_to_ECHO.pl: Dieses Skript habe ich für die Umwandlung von Song Yingxing verwendet. Für europäische Texte müsste es überarbeitet werden.
Besonderheiten bei chinesischen Texten
Version 2.0.1 der chinesischen DESpecs ist hier.
- beachte die in echo-chinese-text definierten Attribute
- 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.0.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.