[XSL oder JavaScript] Zeilenumbrüche aus anderem Text übernehmen

WhiZZler

Chancentod²
ID: 85586
L
6 Mai 2006
588
32
Begrüße!

Erstmal Entschuldigung für den wenig aussagekräftigen Titel. Ich konnte mein Problem irgendwie nicht in einen so kurzen Text packen ;)

Ich habe eine XML Datei, in der ein Text mit Annotationen steht. Zum einen steht darin der Text selbst und dann die Annotationen für die einzelnen Wörter in einer Liste. Übersichtsweise ein Beispiel der XML Datei:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<D-Spin xmlns="https://www.dspin.de/data" version="0.3">
	...
    <TextCorpus xmlns="https://www.dspin.de/data/textcorpus" lang="de">
        <text>Noch einen
 Tag Ruhe!</text>
        <tokens>
            <token ID="t1">Noch</token>
            <token ID="t2">einen</token>
            <token ID="t3">Tag</token>
            <token ID="t4">Ruhe</token>
             <token ID="t5">!</token>
            ...
        </tokens>
        <POStags tagset="STTS">
			<tag tokID="t1" ID="p1">NE</tag>
			<tag tokID="t2" ID="p2">NE</tag>
			<tag tokID="t3" ID="p3">$,</tag>
			<tag tokID="t4" ID="p4">ART</tag>
			<tag tokID="t5" ID="p5">$!</tag>
			...
	</POStags>
    </TextCorpus>
</D-Spin>

Jedes Wort/Token hat eine ID und im Element POStags sind zu diesen IDs die Wortarten gespeichert (die Wortarten stimmen im Beispiel nicht, aber es geht ja um den Aufbau und nicht um die Werte). Daraus möchte ich eine HTML Datei erzeugen (mit XSL, spätere Änderungen mit jQuery), in der es möglich ist, sich unter anderem über Mouseovers die Wortart des aktuelle. Das Zielformat soll dabei dann vereinfacht so aussehen:
PHP:
<span id="t1" class="NE">Noch</span> <span id="t2" class="NE">einen</span> <span id="t3" class="$,">Tag</span> <span id="t3" class="ART">Ruhe</span>

Soweit ist die Transformation kein Problem: über die Tokens iterieren und sich mit XPath die passende Wortart holen. Bei diesem Vorgehen gehen allerdings die Zeilenumbrüche verloren. Diese sind nur in dem Knoten <text/> vorhanden.

Ich bin noch auf keine Lösung gekommen, die mit vernünftigem Rechenaufwand zum Ziel führt. Mein einzige Ansatz war es, den Text aus <text/> zu verwenden, über die tokens zu iterieren und dem Text aus <text/> das <span/> Element hinzuzufügen - dabei muss dann jeweils der Offset beachtet werden. Erstes Rumspielen mit diesem Ansatz hat sich aber als mühsam und wenig effizient erwiesen.

Hat vielleicht jemand einen praktikableren Lösungsvorschlag?

Danke im Voraus,
Mfg,
Whizzler
 
Zuletzt bearbeitet:
Wie wär's mit rückwärts iterieren? Das "erste" Element wäre somit das letzte Wort, hier könnte man Satzzeichen voranstellen. Jedes weiter Element kann man mit einem Leerzeichen trennen. Ist man beim "letzten" Element angelangt ist man am Beginn des Satzes.

E: Zeilenumbrüche? Ok, dann hab ich dein Problem falsch verstanden. Ich sehe keine Zeilenumbrüche in <text>
 
Verständnisfragen zum Problem:

  • Bist du der POSTagger, also generierst du die XML oder is diese vorgegeben und du arbeitest nur mit der Ausgabe des POSTaggers?
  • Hast du mal ein Beispiel mit Umbruch? Werden Umbrüche vom POSTagger als Umbruch/Sonderzeichen/Satzzeichen markiert?
Wenn in den Token keine Satzzeichen sind, im Text aber schon, musst du doch nur durch beide gleichzeitig iterieren. Kommt im Text ein Umbruch, übernimm ihn, ansonsten bearbeite das nächste Token.
 
Gut, das Beispiel war nicht gut gewählt. Ich habe einen Zeilenumbruch in <text> eingefügt. Am Rest ändert sich nichts. Satzzeichen werden in den Tokens aufgelistet, nicht aber die Zeilenumbrüche.

@theHacker:
Die Ausgabe des POSTaggers, also die XML Datei, kommt nicht von mir sondern von einem externen Tool. Das Ziel ist es, die Ausgabe dieses Tools benutzerfreundlich darstellen zu können.

Um das Ganze gleichzeitig iterieren zu können müsste ich den Text nochmals in Tokens zerlegen. Das möchte ich nach Möglichkeit vermeiden. Dafür können verschiedene Tools verwendet werden, die teilweise anderen Output liefern und in der XML Datei selbst ist nicht erkennbar, welches Tool verwendet wurde. Somit wäre das relativ Fehleranfällig.
 
Um das Ganze gleichzeitig iterieren zu können müsste ich den Text nochmals in Tokens zerlegen.
Nö, musst du nicht. Du musst bloß n Byte-Marker mitziehen.
z.B.
Code:
<text>Noch einen[B][COLOR=Red]\n[/COLOR][/B] 
Tag Ruhe!</text>
<tokens>
             <token ID="t1">Noch</token>
             <token ID="t2">einen</token>
             <token ID="t3">Tag</token>
             <token ID="t4">Ruhe</token>
              <token ID="t5">!</token>
Jetzt über Tokens iterieren:
Iteration 1:
tokenID="t1", tokenText="Noch"
text="Noch einen\n Tag Ruhe!"

:arrow: Token mit entsprechendem Markup ausgeben
:arrow: Marker in Text verschieben, 4 Zeichen in Text sind identisch mit dem tokenText
text="Noch einen\n Tag Ruhe!"

Nächstes Zeichen Whitespace-Character? Ja.
Whitespace-Character in Text ab Markierung ansehen: Leerzeichen
:arrow: Leerzeichen ausgeben
:arrow: Marker in Text verschieben, 1 Zeichen in Text ist Leerzeichen
text="Noch_einen\n Tag Ruhe!"

Nächstes Zeichen Whitespace-Character? Nein. :arrow: nächstes Token

Iteration 2:
tokenID="t2", tokenText="einen"
text="Noch_einen\n Tag Ruhe!"

:arrow: Token mit entsprechendem Markup ausgeben
:arrow: Marker in Text verschieben, 5 Zeichen in Text sind identisch mit dem tokenText
text="Noch_einen\n Tag Ruhe!"

Nächstes Zeichen Whitespace-Character? Ja.
Whitespace-Character in Text ab Markierung ansehen: Newline
:arrow: Newline ausgeben
:arrow: Marker in Text verschieben, 1 Zeichen in Text ist Newline
text="Noch_einen\n Tag Ruhe!"

Nächstes Zeichen Whitespace-Character? Ja.
Whitespace-Character in Text ab Markierung ansehen: Leerzeichen
:arrow: Leerzeichen ausgeben
:arrow: Marker in Text verschieben, 1 Zeichen in Text ist Leerzeichen
text="Noch_einen\n_Tag Ruhe!"

Nächstes Zeichen Whitespace-Character? Nein. :arrow: nächstes Token

Iteration 3:
tokenID="t3", tokenText="Tag"
text="Noch_einen\n_Tag Ruhe!"

...

Du siehst hier, dass du alle Whitespace-Zeichen doch sowieso übernehmen musst. Drum fällt mir hier die Frage auf:
Warum is eigentlich das Newline für dich ein Problem? Das Leerzeichen machst du doch auch ohne Probleme. In meinem Algorithmus oben werden Leerzeichen und Newline mit derselben Logik behandelt.
Dafür können verschiedene Tools verwendet werden, die teilweise anderen Output liefern und in der XML Datei selbst ist nicht erkennbar, welches Tool verwendet wurde. Somit wäre das relativ Fehleranfällig.
Wenn du das Tool austauscht und es anderen Output liefert, ists wohl logisch, dass du auch anderen Code für dessen Verarbeitung schreiben musst :ugly:
 
Du siehst hier, dass du alle Whitespace-Zeichen doch sowieso übernehmen musst. Drum fällt mir hier die Frage auf:
Warum is eigentlich das Newline für dich ein Problem? Das Leerzeichen machst du doch auch ohne Probleme. In meinem Algorithmus oben werden Leerzeichen und Newline mit derselben Logik behandelt.

Das klingt unheimlich logisch und auf vom Rechenaufwand her vertretbar. Ich bin anfangs davon ausgegangen einfach nach jedem Token ein Leerzeichen zu setzen. Damit wäre aber wohl kein besonders schöner Output entstanden. Mit deinem vorgeschlagenen Algorithmus können aber sowohl die Leerzeichen als auch die Zeilenumbrüche gesetzt werden. Dankeschön!

Jetzt muss ich nur noch schauen, ob ich das mit JavaScript oder in XSL löse. XSL wäre wahrscheinlich die schönere Lösung, aber darin bin ich nicht wirklich fit.

Wenn du das Tool austauscht und es anderen Output liefert, ists wohl logisch, dass du auch anderen Code für dessen Verarbeitung schreiben musst :ugly:
Es gibt verschiedene Tools, die verschiedene Annotationen liefern. Die also teilweise unterschiedliche Tokens bestimmen und vor allem bei den Wortarten nicht immer zu den gleichen Ergebnissen kommen. Das Format des Outputs ist aber immer das gleiche (nennt sich tcf Format, falls das jemanden interessiert)