Die Motivationen der Frage wurden im folgenden Abschnitt dargestellt. Es gibt viele Möglichkeiten, Text kursiv zu machen , daher gibt es möglicherweise mehr als einen guten " Swap- Kursiv-Algorithmus ". Das Problem zeigt einige zusätzliche Schwierigkeiten in einem XHTML-Code und die Verwendung des <i>
Tags, die ausgeglichen werden müssen . Beispiel:
<!-- original text: -->
<p id="p1"><i>Several more</i> Homo sapiens <i>fossils were discovered</i>.</p>
<!-- same text, swapping italics: -->
<p id="p2">Several more <i>Homo sapiens</i> fossils were discovered.</p>
Sieht also so aus,
Es wurden mehrere weitere Fossilien des Homo sapiens entdeckt .
Es wurden mehrere weitere Fossilien des Homo sapiens entdeckt.
Algoritms Einführung und Diskussion
Bei " Layout-Lösung " überprüft der einfachste Algorithmus die font-style
CSS-Eigenschaft aller Textblöcke und invertiert sie mit jQuery:
$('#myFragment *').each(function(){
if ($(this).css('font-style')=='italic')
$(this).css('font-style','normal')
else
$(this).css('font-style','italic')
});
Aber dieser Algorithmus überlebt einen etwas komplexeren Test nicht.
<p id="p3"><b><i>F</i>RAGMENT <big><i>with italics</i> and </big> withOUT.</b></p>
Der zweiteinfachste Algorithmus ist für eine konkrete Lösung und wurde im Abschnitt "Beispiele" verwendet. Haben Sie zwei Schritte:
- Schließen Sie das XHTML-Fragment kursiv ein.
- kursive Tags zum Öffnen / Schließen invertieren (z. B.
</i>
bis<i>
).
Das heißt, mit Javascript schreiben,
var s = '... a fragment of XHTML content ...';
s = '<i>'+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
'</i>';
Aber auch nicht bis zum zweiten Test überleben, Gleichgewicht der Tags verlieren ... Der "korrigierte" Algorithmus läuft (!), Ist aber nicht portabel, weder schnell noch elegant. Dies wird hier und im folgenden Beispielabschnitt demonstriert .
Der Punkt!
Die Frage ist also:
Gibt es einen einfachen, guten und generischen Algorithmus (in jedem Browser verwendbar und in eine andere Sprache portierbar)? Sie kennen einen anderen "Swap-Kursiv-Algorithmus"?
PS: "generisch" in dem Sinne, dass ich Ihren Algorithmus sogar in XSLT übersetze. Der Algorithmus muss direkt ausgeglichenen XHTML-Code erzeugen (ohne eine zwischengeschaltete Blackbox wie Tidy).
Motivationen
Ich muss den "Swap-Kursiv-Algorithmus" auf Texteditoren, Server-Parser usw. portieren. In allen Fällen kann ich die Eingabe (und Ausgabe) durch Standard-XHTML und <i>
-Tag "normalisieren" .
Ich analysiere XHTML-Text von Prosabüchern und wissenschaftlichen Artikeln, die aus verschiedenen Ursprüngen und Stilen exportiert wurden ... Die meisten Texte werden als "normaler Text" exportiert, aber viele Titel (z. B. Artikeltitel, Kapiteltitel) und manchmal , ein vollständiges Kapitel oder ein vollständiges Textfeld (z. B. Artikelzusammenfassung) sind kursiv dargestellt. Alle diese "mit Kursivschrift stilisiert" müssen invertiert werden. Typische Fälle:
Wandeln Sie die ursprüngliche Kursivschrift "Alle Kapitel kursiv" in "Normaltext für alle Kapitel" um: Siehe diesen Fall , in dem in einem Buch mit etwa 300 Seiten 8 der 25 Kapitel invertiert werden müssen.
Kursiv gedruckte Anführungszeichen, Abstracts usw. Siehe dieses Beispiel . Müssen Sie wieder normal arbeiten, aber ohne die Betonungswörter zu verlieren.
Das Schreiben von Binomialnamen von Arten in wissenschaftlichen Texten wird normalerweise kursiv geschrieben (oder invertiert in einer anderen Schriftart als der für "normalen Text" verwendete). Hunderte von kursiven Titeln (von Artikeln und Artikelabschnitten) von XHTML-exportierten Artikeln müssen an meinem Arbeitsplatz invertiert werden. PS: siehe das Beispiel am Anfang der Frage ("Mehrere weitere Homo sapiens ...").
Ich muss auch den generischen Algorithmus (Ihrer Antwort!) In eine XSLT-Bibliothek übersetzen , in der keine "Tag-Balancing-Korrektur" vorhanden ist.
Beispiele
Implementierung eines nicht generischen "Swap Italics-Algorithmus" in Javascript und PHP . Ein generischer benötigt einen allgemeinen "XML-Interleaving-Algorithmus" ... Hier verwende ich Browser- (DOM) und Tidy-Korrekturen als Alternative zum "Interleaving".
Javascript
Es läuft mit komplexen Eingaben (!). Veranschaulichung durch eine jQuery-Implementierung :
var s = $('#sample1').html(); // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
s = "<i>"+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
"</i>"; // a not-well-formed-XHTML, but it is ok...
$('#inverted').html(s); // ...the DOM do all rigth!
// minor corrections, for clean empties:
s = $('#inverted').html();
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean remain
$('#inverted').html(s);
// END ALGORITHM
alert(s);
PHP, mit ordentlich
Das gleiche wie bei Javascript, das in PHP "übersetzt" wurde - die natürliche Übersetzung verwendet DOMDocument()
Klassen und loadHTML
/ oder saveXML
Methoden, aber was sich genauso verhält wie die Korrespondenten des Browsers, ist die tidy
Klasse . Zeigt die gleichen Ergebnisse (!)
$sample1='<b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b>';
$inverted = '... inverted will be here ...';
echo $sample1;
// Tidy correction
$s = $sample1; // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
$s = "<i>".
preg_replace_callback('/<(\/?)i>/s', function ($m){
return $m[1]? '<i>': '</i>';}, $s) .
"</i>"; // a not-well-formed-XHTML, but it is ok...
$config = array('show-body-only'=>true,'output-xhtml'=>true);
$tidy = new tidy;
$tidy->parseString($s, $config, 'utf8');
$s = $tidy; // ... because Tidy corrects!
// minor corrections, for clean empties:
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean remain
// END ALGORITHM
echo "\n\n$s";
quelle
Antworten:
Aktualisierung (18. Juni 13): Verwenden Sie diese Antwort, um Algorithmen zu erklären und Schlussfolgerungen zusammenzufassen.
Informationen zu Problemumgehungen für jQuery-Traversing und "Layout-Lösung".
Nach dem @ Wilbert-Kommentar habe ich den "einfachsten Algorithmus" angepasst, um das dynamische Verhalten des zu vermeiden
check .prop()
, das sich mit der.each()
Iteration ändert , und das zu entfernenelse
. Nach allen Iterationen wird ein "übergeordneter Kursiv" aufgelöst. Siehe hier oder den Code unten.Eine andere Möglichkeit, mit dem dynamischen Verhalten umzugehen, besteht darin, eine statische Eigenschaft zu überprüfen, indem sie
prop('tagName')
sich nicht ändert. Siehe hier oder den Code unten.Es sind weitere Tests und eine endgültige Analyse erforderlich, um die Stileigenschaften in konkrete
<i>
Tags zu ändern . Um den Algorithmus zweimal anzuwenden, benötigen wir einige Sorgfalt.Layout-Lösung
Dies ist keine Lösung für die vorliegende Frage, liefert aber einige gute Hinweise und ist die beste (zumindest die kleinste!) Lösung für das "Layoutproblem"!
Die
toggleClass()
Methode kann verwendet werden, um von einer "kursiven Klasse" zu einer "normalen Textklasse" zu wechseln. Siehe hier oder den Code unten.Und wir können diesen kleinen Algorithmus zweimal und so oft anwenden, wie wir wollen ... Es ist eine gute Lösung! Aber es ist kein "XML-Algorithmus umschreiben", das CSS ist hier ein Schlüssel :
... Für einen Algorithmus, der
<i>
Tags transformiert , ist das Problem also noch offen ...Konkrete Lösung
Eine "100% ige Lösung in reinem XSLT1" (in vielen Fällen getestet!) Basierend auf einer Adaption von @ DanielHaley's . Es ist eine effektive
<i>
Tag-Transformation.Gliederung als "Drive-by-Event-Algorithmus" in einem Kopiervorgang:
i
Tags entfernen : Kopieren Sie alles von "<i>
Ding</i>
" als " Ding ".i
Tags einschließen : Kopieren Sie einen beliebigen Text als "<i>
Text</i>
", wenn sich der Text nicht in einem Kontext kursiver Eltern befindet. PS: Text ist ein Endknoten des DOM-Baums.Schlussfolgerungen
"Layout-Lösungen" eignen sich gut für Texteditoren , verwenden jedoch einige Tricks und nicht strenge Lösungen (unabhängig von Überlappungen, Leistung usw.). Für den XML-Prozess müssen wir uns mit der
<i>
Transformation von Tags befassen ... Die natürlichen Sprachen zum Ausdrücken des Algorithmus sind also XSLT oder xQuery.Der mit XSLT implementierte Algorithmus zeigt die Framework-Notwendigkeiten:
der Ahnen- Selektor (Eltern, Großeltern usw.), um zu überprüfen, ob es sich um einen "kursiven Kontext" handelt oder nicht;
der Textknotenzugriff (DOM
text()
);Entfernen Sie das
i
Tag und fügen Sie es hinzu.So können wir die Probleme mit jedem Framework sehen.
DOM (das W3C-Standardframework): Das
DOMDocument::renameNode()
für Punkt 3 ist noch nicht implementiert (siehe PHP, Javascript usw.).jQuery: hat keine praktische Funktion für Punkt 2, siehe diese Antwort .
XSLT: Das Beste, um den Algorithmus auszudrücken, ist jedoch in keinem Kontext wie Javascript verfügbar.
Ich (oder Sie bitte!) Werde versuchen, den XSLT-Algorithmus mit "reinen DOM2" -Methoden auszudrücken. Diese DOM-Version wird der "generische Algorithmus" sein ... Nun: Wenn die Übersetzung nur für DOM3 gültig ist (unter Verwendung von renameNode und anderen Tricks), lautet die Schlussfolgerung vorerst: "Es gibt KEINEN generischen / übersetzbaren Algorithmus".
quelle
XSLT-Versuch von https://stackoverflow.com/a/17156452/317052 ...
Ich bin nicht sicher, ob dies alle Fälle abdecken würde, aber Sie könnten dies tun:
XML-Eingabe
XSLT 1.0
XML-Ausgabe
Eingabe gerendert
Es wurden mehrere weitere Fossilien des Homo sapiens entdeckt .
Es wurden mehrere weitere Fossilien des Homo sapiens entdeckt.Lass mich allein!
O RIGINAL mit Kursivschrift und OHNE
Ausgabe gerendert
Es wurden mehrere weitere Fossilien des Homo sapiens entdeckt .
Es wurden mehrere weitere Fossilien des Homo sapiens entdeckt.Lass mich allein!
O RIGINAL mit Kursivschrift und OHNE
quelle
Ich würde einfach:
<i>
in</i>
s</i>
in<i>
s<i>
am Anfang hinzu</i>
am Ende hinzuDamit
quelle
<b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b>
... er produziert unausgeglichenen (verbotenen!) Code und leere Blöcke .<i><b></i>O<i>RIGINAL <big></i>with italics<i> and </big> withOUT</b></i>
mag nicht schön sein, aber es funktioniert in jedem Browser<i><b></i>
ist nicht, und bei ALL DISCUSSION HERE geht es um "einen Algorithmus, der ausgewogene Ergebnisse liefert".