Ваша первая задача - выбрать формат патча.Самый сложный формат для чтения людьми (IMHO) оказывается самым простым форматом для программного обеспечения: скрипт ed (1).Вы можете начать с простого /usr/bin/diff -e old.xml new.xml
для генерации патчей; diff (1) будет производить линейно-ориентированные патчи, но это должно быть хорошо для начала.Формат ed выглядит следующим образом:
36a
<tr><td class="eg" style="background: #182349;"> </td><td><tt>#182349</tt></td></tr>
.
34c
<tr><td class="eg" style="background: #66ccff;"> </td><td><tt>#xxxxxx</tt></td></tr>
.
20,23d
Числа - это номера строк, диапазоны номеров строк разделяются запятыми.Тогда есть три однобуквенные команды:
- a : добавить следующий блок текста в этой позиции.
- c : изменитьтекст в этой позиции до следующего блока.Это эквивалентно d , за которым следует команда a .
- d : удалить эти строки.
Вы также заметите, что номера строк в патче идут снизу вверх, поэтому вам не нужно беспокоиться об изменениях, запутывающих номера строк в последующих фрагментах патча.Фактические фрагменты текста, которые будут добавлены или изменены, следуют за командами в виде последовательности строк, оканчивающихся строкой с одним периодом (то есть /^\.$/
или patch_line == '.'
в зависимости от ваших предпочтений).Таким образом, формат выглядит следующим образом:
[line-number-range][command]
[optional-argument-lines...]
[dot-terminator-if-there-are-arguments]
Итак, чтобы применить патч ed , все, что вам нужно сделать, это загрузить целевой файл в массив (по одному элементу в строке), проанализируйте патч, используя простой конечный автомат, вызовите Array # insert , чтобы добавить новые строки, и Array # delete_at , чтобы удалить их.Для написания патчера не нужно более пары десятков строк Ruby, и библиотека не нужна.
Если вы можете организовать свой XML-код так:
<tag>
blah blah
</tag>
<other-tag x="y">
mumble mumble
</other>
чем:
<tag>blah blah</tag><other-tag x="y">mumble mumble</other>
тогда вышеупомянутый простой линейно-ориентированный подход будет работать нормально;дополнительные EOL не будут стоить много места, поэтому начните с простой реализации.
Существуют библиотеки Ruby для создания diff-файлов между двумя массивами (для начала google "rubygorithm :: diff").Объединение библиотеки diff с анализатором XML позволит вам создавать патчи, основанные на тегах, а не на строках, и это может подойти вам лучше.Важным моментом является выбор форматов патчей: как только вы выберете формат ed (и поймете, как правильно работает патч снизу вверх), все остальное в значительной степени становится на свои места без особых усилий.