Я являюсь автором библиотеки diff / match / patch из Google в виде простого текста.
Ключевой вопрос - точны ли ваши патчи. В идеальном мире:
diff(old_text, new_text) -> edits
patch(edits, old_text) -> new_text
Обратите внимание, что базовый текст (old_text) одинаков в обеих операциях. В этом идеальном случае простой текстовый diff и патч будут отлично работать независимо от типа содержимого. Если этот случай относится к вам, то вы сделали.
Проблема заключается в нечетких исправлениях. Вот соответствующий пример:
diff(old_text, new_text) -> edits
patch(edits, old_forked_text) -> new_forked_text
Обратите внимание, что базовый текст не одинаков в обеих операциях. Они должны быть похожими, но операция исправления теперь должна использовать «суждение» о том, что она должна делать. Некоторые патчи могут соответствовать идеально, как указано в редактировании, другие могут нуждаться в настройке для положения, другие могут нуждаться в настройке для измененного контекста, другие могут не соответствовать вообще и должны быть отброшены. Если ваш алгоритм исправления не знает о структуре XML при принятии своих решений, вы вполне можете получить неправильно сформированный XML. Вот пример:
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>
Давайте посмотрим на это внимательно. Исходный diff вернул два редактирования, изменив внешний SPAN на DIV. Простое изменение. К сожалению, текст, к которому применяется это изменение, изменился по сравнению с оригиналом. Слово «Jabberwock» было удалено. Теперь первое изменение SPAN-> DIV соответствует второму тегу SPAN, а не первому. Поскольку алгоритм исправления не знает правил XML, он приводит к незаконно вложенным тегам.
Существуют некоторые хаки, которые позволяют вам гарантировать действительный XML при использовании простого текстового патча, но они приводят к некоторой потере гибкости (исходный вопрос уже имеет ссылку на вики-страницу, о которой я писал). Конечно, наилучшим решением для исправления XML является использование алгоритма diff и patch с учетом XML. Это значительно сложнее и дороже, но они существуют. Назовите имена Танкреда Линдхольма и Себастьяна Реннау за огромную работу, проделанную ими в области XML (особенно в отношении DocEng).
Дайте мне знать, могу ли я добавить еще что-нибудь.
- Нил Фрейзер