Ich arbeite in Flex / AS3 (zur Vereinfachung) einen XML-Editor. Ich muss die Funktion zum Rückgängigmachen / Wiederherstellen bereitstellen.
Eine Lösung besteht natürlich darin, den gesamten Quelltext bei jeder Bearbeitung zu speichern. Um Speicherplatz zu sparen, möchte ich jedoch stattdessen die Diffs speichern (diese Diffs werden auch verwendet, um Updates zum automatischen Speichern an den Server zu übertragen).
Meine Frage ist - kann ich einen Klartext-Diff-Algorithmus zum Verfolgen dieser XML-Änderungen verwenden?
Meine Recherchen im Internet zeigen, dass ich das nicht tun kann . Ich vermisse jedoch offensichtlich etwas. Plaintext diff bietet Funktionen, die angeblich:
%Vor%XML ist einfach Text, warum kann ich nicht einfach diff () und patch () verwenden, um den Text zuverlässig zu transformieren?
Zum Beispiel: Sagen wir, ich bin ein Poet. Wenn ich Gedichte schreibe, verwende ich viele funky Interpunktionen ... Sie wissen, wie & lt ;, / und & gt ;. (Sie könnten sehen, wohin ich damit gehe ...) Wenn ich meine Gedichte in einer Anwendung schreibe, die Diffs verwendet, um Funktionen rückgängig zu machen, wird meine Poesie verstümmelt, wenn ich meine Bearbeitungen rückgängig mache? Es ist nur Text! Warum macht es einen Unterschied für den Algorithmus?
Ich verstehe hier offensichtlich nichts. Danke fürs Erklären! :)
UPDATE:
Einige Diskussion, die ich in Bezug auf das Diffing von XML mit einem Klartext-Algorithmus gemacht habe:
Ich verstehe auch, dass ein Befehlsmuster wahrscheinlich eine bessere Methode zur Implementierung von Undo / Redo ist. Ich habe meinen Anwendungsfall der Einfachheit halber vereinfacht, und ich denke immer noch, dass XML-Diffing der beste Ansatz ist.
Ich bin der Autor der Plain-Text-diff / match / patch-Bibliothek von Google.
Die Schlüsselfrage ist, ob Ihre Patches exakt sind. In einer idealen Welt:
%Vor%Beachten Sie, dass der Basistext (old_text) in beiden Operationen identisch ist. In diesem idealen Fall funktioniert ein einfaches Text-Diff und -Patch perfekt, unabhängig von der Art des Inhalts. Wenn dieser Fall auf Sie zutrifft, sind Sie fertig.
Das Problem liegt im unscharfen Patching. Hier ist das entsprechende Beispiel:
%Vor%Beachten Sie, dass der Basistext in beiden Operationen nicht identisch ist. Sie sollten ähnlich sein, aber die Patch-Operation muss nun "beurteilen", was sie tun soll. Einige Patches passen möglicherweise genau wie in der Bearbeitung angegeben, andere müssen möglicherweise für die Position optimiert werden, andere müssen möglicherweise für einen veränderten Kontext optimiert werden, andere passen möglicherweise überhaupt nicht und sollten gelöscht werden. Wenn Ihr Patching-Algorithmus die XML-Struktur bei seinen Entscheidungen nicht kennt, kann es passieren, dass Sie schlechtes XML erhalten. Hier ist ein Beispiel:
%Vor%Schauen wir uns das sorgfältig an. Das ursprüngliche diff gab zwei Änderungen zurück, änderte den äußersten SPAN in einen DIV. Einfache Änderung. Leider hat sich der Text, auf den diese Änderung angewendet wird, gegenüber dem Original geändert. Das Wort "Jabberwock" wurde entfernt. Jetzt stimmt die erste SPAN- & gt; DIV-Änderung mit der zweiten SPAN-Markierung überein, nicht mit der ersten. Da der Patch-Algorithmus die Regeln von XML nicht kennt, führt dies zu illegal verschachtelten Tags.
Es gibt einige Hacks, die es erlauben, ein gültiges XML zu garantieren, wenn Sie einen Plain-Text-Patch verwenden, aber sie führen zu einem gewissen Verlust an Flexibilität (die ursprüngliche Frage hat bereits einen Link zu der Wiki-Seite, die ich darüber geschrieben habe). Die ultimative Lösung zum Patchen von XML ist natürlich die Verwendung eines XML-fähigen Diff- und Patch-Algorithmus. Diese sind wesentlich komplizierter und teurer, aber sie existieren. Google die Namen Tancred Lindholm und Sebastian Rönnau für die großartige Arbeit, die sie im Bereich XML geleistet haben (insbesondere in Bezug auf DocEng).
Lass es mich wissen, wenn ich noch etwas hinzufügen kann.
- Neil Fraser
Ich benutze Beyond Compare ständig, um XML-Dokumente zu vergleichen. Es versteht XML bis zu einem gewissen Grad.
Möglicherweise müssen Sie die beiden Dokumente vorverarbeiten, damit der Textvergleich die bestmögliche Arbeit leistet. In einigen XML-Dokumenten spielt die Reihenfolge einiger Elemente keine Rolle. Es wird sicherlich wichtig für Ihr Diff-Tool sein! Möglicherweise müssen Sie das XML mithilfe einer XML-Transformation vorverarbeiten, die diese Elemente in einer gemeinsamen Reihenfolge in beiden Dateien sortiert, bevor Sie die beiden sortierten Dateien vergleichen.
Sie werden auch den gleichen Einzug für beide Dokumente verwenden wollen. Ich finde es nützlich, jedes Element in einer neuen Zeile zu beginnen und für jede Ebene die gleiche Einrückung mit Leerzeichen zu verwenden. Wenn Ihr Dokument sehr tief wird, sollten Sie nur ein oder zwei Leerzeichen pro Ebene verwenden, damit der Vergleich auf dem Bildschirm angezeigt wird. Sie können sogar ein Attribut pro Zeile verwenden (und die Attribute in eine gemeinsame Reihenfolge sortieren).
Wenn Sie der einzige "Besitzer" der Daten zwischen Ihren Undo / Redo-Punkten sind, dann können Sie natürlich auch plaintext diff verwenden. Wie Sie unterstreichen, handelt es sich um eine Reihe von Transformationen.
Je nach den von Ihnen bereitgestellten Vorgängen ist jedoch der plaintext diff möglicherweise nicht annähernd optimal für die Aufnahme von Rückgängig / Wiederherstellen und Sie müssen möglicherweise bestimmte Fälle spezialisieren. Stellen Sie sich vor, Sie würden nur einen ReplaceAll-Befehl aufzeichnen, der nur einige Bytes Overhead zuzüglich der Such- und Ersetzungszeichenfolge enthält. Das könnte massive Klartext-Diffs erzeugen.
Wenn Sie im weiteren Kontext die externe Bearbeitung dieser Dokumente erlauben und darüber nachdenken, wie Sie Deltas auf dem Server speichern, imitieren Sie Git oder andere Versionskontrollsysteme. Sie müssen eine Art diff-Algorithmus verwenden, da das bloße Aufzeichnen Ihrer Befehle nicht die einzige Transformationsquelle ist. An diesem Punkt beginnst du, Rückgängig / Wiederholen mit Versionskontrolle zu mischen und du solltest vielleicht darüber nachdenken, diese Konzepte für deine Benutzer zu verwirren.
Ich würde in einer Editier-Sitzung die Bearbeitung rückgängig machen und die externe Bearbeitung verbieten, solange die Datei geöffnet ist. Das erlaubt Ihnen, Ihre Befehlsaufzeichnung für breite Fälle zu optimieren, wie ich oben sagte.
Darüber hinaus können Sie entweder die konventionelle Versionskontrolle verwenden (in Betracht ziehen, git zu verpacken) oder Ihre eigene Methode implementieren, mit Dateien umzugehen, die außerhalb Ihres Editors geändert werden.
Ich denke, dass Sie text diff für xml verwenden können, besonders in Ihrem Fall, wo der Mensch die XML Zeile für Zeile schreiben wird. Ich weiß nicht, welche Informationen Sie sagen, dass Sie das nicht tun können, aber ich denke, diese Aussage basierte auf der Tatsache, dass Leerzeichen (Leerzeichen, Tabulatoren, Zeilenumbrüche ...) etwas anders sind als in einer einfachen Textdatei könnte dazu führen, dass zwei verschiedene Textdateien aus einer XML-Perspektive identisch sind. Aber für einen Redakteur, der auf den Menschen abzielt, sehe ich nicht, warum du das nicht kannst.