Posso utilizzare un algoritmo di confronto in testo normale per tenere traccia delle modifiche XML?

StackOverflow https://stackoverflow.com/questions/2430083

  •  19-09-2019
  •  | 
  •  

Domanda

Sto lavorando in Flex/AS3 su (per semplicità) un editor XML.Devo fornire la funzionalità di annullamento/ripetizione.

Naturalmente, una soluzione è memorizzare l'intero testo sorgente con ogni modifica.Tuttavia, per risparmiare memoria, vorrei invece memorizzare le differenze (queste differenze verranno utilizzate anche per trasmettere gli aggiornamenti al server per il salvataggio automatico).


La mia domanda è: posso utilizzare un algoritmo di confronto in testo normale per tenere traccia di queste modifiche XML?

La mia ricerca su Internet indica che I non può fare così.Tuttavia, evidentemente mi manca qualcosa.Diff testo in chiaro fornisce funzionalità che presumibilmente sono:

diff(text, text') -> diffs
patch(text, diffs) -> text'

XML è semplicemente testo, quindi perché non posso semplicemente usare diff() e patch() per trasformare il testo in modo affidabile?

Per esempio:Diciamo che sono un poeta.Quando scrivo poesie, uso molta punteggiatura strana...Sai, come <, / e >.(Potresti capire dove voglio arrivare con questo...) Se scrivo la mia poesia in un'applicazione che utilizza diff per fornire funzionalità di annullamento/ripristino, la mia poesia diventa confusa quando annullo/ripeto le mie modifiche?È solo testo!Perché fa la differenza per l’algoritmo?

Ovviamente non capisco qualcosa qui... Grazie per la spiegazione!:)

AGGIORNAMENTO:

Alcune discussioni che ho incontrato riguardo alla differenza XML con un algoritmo di testo in chiaro:


Inoltre, capisco che un modello di comando è probabilmente un modo migliore per implementare Annulla/Ripeti.Ho semplificato il mio caso d'uso per ragioni di semplicità e continuo a pensare che la differenza XML sia l'approccio migliore.

È stato utile?

Soluzione

Sono l'autore del / partita libreria di testo semplice diff / patch da parte di Google.

La questione chiave è se le patch sono esatte. In un mondo ideale:

  diff(old_text, new_text) -> edits
  patch(edits, old_text) -> new_text

Si noti che il testo base (OLD_TEXT) è la stessa in entrambe le operazioni. In questo caso ideale, quindi un semplice diff testo semplice e la patch funziona perfettamente, indipendentemente dal tipo di contenuto. Se questo caso si applica a voi, allora il gioco è fatto.

Il problema è con patch sfocata. Ecco l'esempio corrispondente:

  diff(old_text, new_text) -> edits
  patch(edits, old_forked_text) -> new_forked_text

Si noti che il testo base non è la stessa in entrambe le operazioni. Essi dovrebbero essere simili, ma l'operazione patch è ora di usare "giudizio" su ciò che dovrebbe fare. Alcune patch possono adattarsi perfettamente come specificato nella modifica, gli altri possono avere bisogno di essere ottimizzato per la posizione, gli altri possono avere bisogno di essere ottimizzato per il contesto alterato, altri potrebbero non essere adatte a tutti e dovrebbe essere eliminato. Se il vostro algoritmo di patch non è a conoscenza della struttura del XML quando le sue decisioni, si può benissimo finire con XML malfromed. Ecco un esempio:

  old_text = Jabberwock<SPAN>Hello<SPAN>World</SPAN></SPAN>
  new_text = Jabberwock<DIV>Hello<SPAN>World</SPAN></DIV>
  diff(old_text, new_text) -> edits
  edits = ["SPAN" -> "DIV" @ character 11,
           "SPAN" -> "DIV" @ character 41]
  old_forked_text = <SPAN>Hello<SPAN>World</SPAN></SPAN>
  patch(edits, old_forked_text) -> new_forked_text
  new_forked_text = <SPAN>Hello<DIV>World</SPAN></DIV>

Diamo un'occhiata a questo con attenzione. Il diff originale restituito due modifiche, modificare l'intervallo più esterna ad un DIV. cambiamento semplice. Purtroppo il testo viene applicata questa modifica a è cambiato rispetto all'originale. La parola "Jabberwock" è stata rimossa. Ora la prima SPAN-> DIV cambiamento corrisponde con il secondo tag SPAN, non il primo. Dal momento che l'algoritmo di patch non è a conoscenza delle regole di XML, il risultato e 'tag annidati illegalmente.

Ci sono alcuni hack che permettono di garantisci XML valido quando si utilizza una patch testo semplice, ma risultano in qualche perdita di flessibilità (domanda originale ha già un link alla pagina wiki che ho scritto su questo). La soluzione definitiva per l'applicazione di patch XML è ovviamente quello di utilizzare un algoritmo diff e patch di XML-aware. Questi sono molto più complicati e costosi, ma esistono. Google i nomi di Tancredi Lindholm e Sebastian Rönnau per il grande lavoro che hanno fatto nel campo XML (in particolare per quanto riguarda la doceng).

Fatemi sapere se c'è qualcos'altro che posso aggiungere.

- Neil Fraser

Altri suggerimenti

Beyond Compare tutto il tempo per confrontare i documenti XML. Si capisce XML, in una certa misura.

Potrebbe essere necessario pre-processo i due documenti in ordine per confronto testuale di fare il miglior lavoro possibile. Per esempio, in alcuni documenti XML, l'ordine di alcuni elementi potrebbe non importa. Sarà certamente un problema per il vostro strumento diff! Potrebbe essere necessario pre-processo di XML utilizzando un XML Transform che ordina questi elementi in un ordine comune a entrambi i file, prima di confrontare i due file ordinati.

Si sta anche andando a voler usare lo stesso rientro per entrambi i documenti. Trovo utile per avviare ogni elemento su una nuova linea, e di utilizzare la stessa quantità di rientro, con spazi, per ogni livello. Se il documento diventa molto profonda, che si desidera utilizzare solo uno o due spazi per livello, in modo che il confronto si adatta allo schermo. Si potrebbe anche voler utilizzare un attributo per linea (e per ordinare gli attributi in un ordine comune).

Se sei l'unico "proprietario" dei dati tra i tuoi punti di annullamento/ripetizione, ovviamente puoi utilizzare il diff in testo semplice per essi.Come hai sottolineato, si tratta di un insieme di trasformazioni.

A seconda delle operazioni fornite, tuttavia, il diff del testo in chiaro potrebbe non essere neanche lontanamente ottimale per la registrazione di operazioni di annullamento/ripetizione e potrebbe essere necessario specializzare determinati casi.Immagina di registrare semplicemente un comando Sostituisci tutto che potrebbe comportare solo pochi byte in più più la stringa di ricerca e sostituzione.Ciò potrebbe generare enormi differenze nel testo in chiaro.

Nel contesto più ampio, se consenti la modifica esterna di questi documenti e stai pensando di più a come archiviare i delta sul server, stai imitando git o altri sistemi di controllo della versione.Devi usare una sorta di algoritmo di differenza perché la semplice registrazione dei tuoi comandi non è ovviamente l'unica fonte di trasformazione.A questo punto stai iniziando a combinare l'annullamento/ripristino con il controllo della versione e potresti voler riflettere attentamente su come confondere questi concetti per i tuoi utenti.

Continuerei ad annullare/ripetere come all'interno di una sessione di modifica e vieterei la modifica esterna mentre il file è aperto.Ciò ti consente di ottimizzare la registrazione dei comandi per casi ampi, come ho detto sopra.

Oltre a ciò, usa il controllo della versione convenzionale (considera il confezionamento di git) o ​​implementa il tuo modo di gestire i file modificati al di fuori del tuo editor.

Penso che si possa utilizzare diff di testo per xml soprattutto nel tuo caso in cui esseri umani scriverà la linea xml per riga. Non so quali informazioni ti hanno detto non è possibile farlo, ma immagino che la dichiarazione era basata sul fatto che i caratteri di spazio (spazio, tabulazione, nuova linea ...) sono un po 'diverse che si trovano in un file di testo, che potrebbe tradursi in due file di testo differenti sono identici dal punto di vista XML. Ma ancora una volta, per un editore mira essere umano, non vedo il motivo per cui non si può.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top