¿Puedo utilizar un algoritmo de diff texto plano para el seguimiento de los cambios XML?

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

  •  19-09-2019
  •  | 
  •  

Pregunta

Estoy trabajando en Flex / AS3 sobre (para simplificar) un editor XML. Necesito para proporcionar la funcionalidad de deshacer / rehacer.

Por supuesto, una solución es almacenar todo el texto original con cada edición. Sin embargo, para conservar la memoria, me gustaría para almacenar los diferenciales lugar (estas diferenciaciones también serán utilizados para transmitir actualizaciones al servidor para auto-guardar).


Mi pregunta es - ¿Puedo usar un algoritmo de diff texto plano para el seguimiento de estos cambios XML

Mi investigación en Internet indica que I No puedo hacerlo. Sin embargo, obviamente estoy perdiendo algo. diff texto plano proporciona funcionalidad que es supuestamente:

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

XML es simplemente el texto, ¿por qué no puedo simplemente usar diff () y el parche () para transformar el texto de forma fiable?

Por ejemplo: Digamos que soy un poeta. Cuando escribo poesía, yo uso un montón de puntuacion cobarde ... Ya sabes, como <, /, y>. (Es posible que vea a dónde voy con esto ...) Si estoy escribiendo mi poesía en una aplicación que utiliza diffs para proporcionar la funcionalidad de deshacer / rehacer, se convierte en ilegible mi poesía cuando deshacer / rehacer mis ediciones? Es sólo texto! ¿Por qué hacer una diferencia en el algoritmo?

Yo, obviamente, no consigo algo aquí ... Gracias por la explicación! :)

ACTUALIZACIÓN:

Algunas discusiones que he encontrado en relación con diffing XML con un algoritmo de texto llano:


Además, entiendo que un patrón de comando es probable que una mejor manera de poner en práctica de deshacer / rehacer. He simplificado mi caso de uso en aras de la simplicidad, y yo sigo pensando que diffing XML es el mejor enfoque.

¿Fue útil?

Solución

Soy el autor de la / partido de la biblioteca de texto sin formato de diferencias / parche de Google.

La cuestión clave es si los parches son exactas. En un mundo ideal:

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

Observe que el texto base (texto_original) es la misma en ambas operaciones. En este caso ideal, entonces un simple diff de texto sin formato y el parche funcione a la perfección, con independencia del tipo de contenido. Si este caso se aplica a usted, entonces ya está.

El problema reside en parches difusos. Aquí está el ejemplo correspondiente:

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

Observe que el texto base no es la misma en ambas operaciones. Ellos deben ser similares, pero la operación de parche ahora tiene que utilizar "juicio" sobre lo que debe hacer. Algunos parches pueden encajar perfectamente como se especifica en la edición, otros pueden necesitar ser ajustado para la posición, otros pueden necesitar ser ajustado para el contexto alterado, otros pueden no ajustarse en absoluto y debe suprimirse. Si el algoritmo de parcheo no tiene conocimiento de la estructura del XML al hacer sus decisiones, puede muy bien terminar con XML malfromed. He aquí una muestra:

  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>

Veamos éste con cuidado. El diff originales vueltos dos ediciones, cambie el SPAN más externa a un DIV. simple cambio. Por desgracia, el texto se está aplicando esta edición ha cambiado a partir del original. La palabra "Jabberwock" se ha eliminado. Ahora, la primera ñol> DIV cambio coincide con la segunda etiqueta SPAN, no el primero. Dado que el algoritmo parche no es consciente de las reglas de XML, el resultado es ilegal etiquetas anidadas.

Hay algunos trucos que le permiten garantizar XML válido cuando se utiliza un parche de texto sin formato, pero dan como resultado una pérdida de flexibilidad (la pregunta original ya tiene un enlace a la página wiki que escribí sobre esto). La solución definitiva para parchear XML es, por supuesto, el uso de un algoritmo de diff y patch XML-aware. Estos son significativamente más complicado y costoso, pero existen. Google los nombres de Tancredo y Sebastian Lindholm Ronnau por el gran trabajo que han hecho en el campo de XML (en particular en lo que respecta a DocEng).

Quiero saber si hay algo más que pueda agregar.

- Neil Fraser

Otros consejos

que no tiene comparación todo el tiempo para comparar los documentos XML. Se entiende XML, hasta cierto punto.

Es posible que necesite pre-proceso de los dos documentos con el fin de comparación textual de hacer el mejor trabajo posible. Por ejemplo, en algunos documentos XML, del orden de algunos elementos puede no importar. Sin duda, la materia a su herramienta de diferencias! Es posible que necesite pre-procesar el XML usando una transformación XML que ordena estos elementos en un orden común en ambos archivos, antes de comparar los dos archivos ordenados.

También vas a querer utilizar el mismo sangrado de ambos documentos. Me parece útil para comenzar cada elemento en una nueva línea, y utilizar la misma cantidad de sangría, con espacios, para cada nivel. Si el documento se vuelve muy profunda, que se desea utilizar sólo uno o dos espacios por nivel, por lo que la comparación se ajusta en la pantalla. Incluso puede que desee utilizar un atributo por línea (y para ordenar los atributos en un orden común).

Si usted es el único "dueño" de los datos entre el deshacer / rehacer puntos entonces por supuesto que puede usar diff texto plano para ellos. Como usted señala, que equivale a un conjunto de transformaciones.

En función de las operaciones que ofrece, sin embargo, diff texto plano puede no ser remotamente cerca óptimo para deshacer la grabación / rehacer y puede ser necesario especializarse ciertos casos. Imagínese simplemente grabar un comando ReplaceAll que podría ser sólo unos pocos bytes de cabecera más la búsqueda y reemplazo de cadenas. Eso podría generar diffs masivos de texto plano.

En el contexto más amplio, si se permite la edición externa de estos documentos, y que está pensando más en cómo almacenar los deltas en el servidor, que está imitando a otros sistemas de control de versiones Git o. Usted tiene que utilizar algún tipo de algoritmo de cambio debido simplemente a grabar sus comandos obviamente no es la única fuente de transformación. En este punto usted está comenzando a mezclar deshacer / rehacer con control de versiones y es posible que desee pensar seriamente en confundir los conceptos para sus usuarios.

Me gustaría mantener deshacer / rehacer como dentro de una sesión de edición y la prohibición de edición externa, mientras que el archivo está abierto. Eso le permite optimizar su grabación de comandos para los casos generales como he dicho anteriormente.

Más allá de eso, o bien utilizar el control de versiones convencionales (considere envolver GIT) o poner en práctica su propia manera de hacer frente a los archivos que se cambian fuera de su editor.

Creo que se puede usar diff texto para XML especialmente en el caso en el que el ser humano va a escribir la línea xml por línea. No sé qué información tienes diciendo que no se puede hacer eso, pero supongo que la declaración se basó en el hecho de que los caracteres de espacio (espacio, tabulación, nueva línea ...) son algo diferentes que se encuentran en un archivo de texto sin formato, que podría dar lugar a dos diferentes archivos de texto son idénticos desde el punto de vista XML. Pero, de nuevo, para un editor de focalización ser humano, no veo por qué no se puede.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top