Как я должен управлять различными несовместимыми формами документов на основе Xml

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

Вопрос

У меня есть приложение, которое сохраняет документы (например, документы Word) в формате на основе Xml - в настоящее время классы C #, созданные из файлов xsd, используются для чтения / записи формата документа, и все было хорошо до недавнего времени, когда мне пришлось изменить формат документа.Меня беспокоит обратная совместимость в качестве будущих версий моего приложения потребность чтобы иметь возможность читать документы, сохраненные всеми предыдущими версиями, и в идеале я также хочу, чтобы более старые версии моего приложения могли корректно обрабатывать чтение документов, сохраненных будущими версиями моего приложения.

Например, предположим, что я изменил схему своего документа, чтобы добавить где-нибудь (необязательный) дополнительный элемент, тогда более старые версии моего приложения просто проигнорируют дополнительный элемент, и проблем не возникнет:

<doc>
    <!-- Existing document -->
    <myElement>Hello World!</myElement>
</doc>

Однако, если вносятся критические изменения (например, атрибут преобразуется в элемент или коллекцию элементов), то прошлые версии моего приложения должны либо игнорировать этот элемент, если он необязателен, либо информировать пользователя о том, что в противном случае они пытаются прочитать документ, сохраненный в более новой версии моего приложения.Также это в настоящее время вызывает у меня головную боль, поскольку для чтения двух разных документов всем будущим версиям моего приложения нужен совершенно отдельный код.

Примером такого изменения может быть следующий xml-файл:

<doc>
    <!-- Existing document -->
    <someElement contents="12" />
</doc>

Переход на:

<doc>
    <!-- Existing document -->
    <someElement>
        <contents>12</contents>
        <contents>13</contents>
    </someElement>
</doc>

Чтобы предотвратить проблемы со службой поддержки в будущем, я хотел разработать достойную стратегию обработки изменений, которые я могу внести в будущем, чтобы версии моего приложения, которые я выпускаю сейчас, могли справляться с этими изменениями в будущем:

  • Должен ли "номер версии" документа храниться в самом документе, и если да, то какую стратегию управления версиями следует использовать?Должна ли версия документа соответствовать версии .exe assembly, или следует использовать более сложную стратегию (например, значительные изменения в редакции указывают на критические изменения, в то время как незначительные изменения в редакции указывают на неразрывные изменения - например, дополнительные необязательные элементы)
  • Какой метод я должен использовать для чтения самого документа и как мне избежать репликации огромных объемов кода для разных версий документов?
    • Хотя XPath, очевидно, наиболее гибкий, его реализация требует гораздо больше работы, чем простое создание классов с помощью xsd.
    • С другой стороны, если используется синтаксический анализ DOM, то для каждого критического изменения в системе управления версиями потребуется новая копия документа xsd, что вызовет проблемы, если когда-либо потребуется применить исправления к старым схемам (старые версии приложения все еще поддерживаются).

Кроме того, я проработал все это очень свободно, исходя из предположения, что все вносимые мной изменения могут быть разделены на эти две категории: "основные изменения" и "неразрывные изменения", но я не совсем уверен, что это безопасное предположение.

Обратите внимание, что я использую термин "документ" очень свободно - содержимое вообще не похоже на документ!

Спасибо за любой совет, который вы можете мне дать.

Это было полезно?

Решение

Вам определенно нужен номер версии в XML-файле, и я бы посоветовал не привязывать его к версии приложения, потому что это действительно отдельная сущность.Вы можете использовать две или три версии своего приложения, даже не меняя формат XML, или вам может потребоваться изменять формат несколько раз в ходе разработки одного выпуска.

Если вы хотите, чтобы более старые версии приложения могли читать более новые версии XML-файла, вы никогда не сможете удалять элементы или изменять их имена.Вы всегда можете добавить элементы, и старый код с радостью проигнорирует их (одна из приятных особенностей XML), но если вы удалите их, старый код не сможет функционировать.

Как сказал Ишмаэль, XSLT - это хороший способ преобразовать формат XML из одной версии в другую, чтобы вам не пришлось использовать целую кучу процедур синтаксического анализа в вашем исходном коде.

Другие советы

XSLT - очевидный выбор здесь.Учитывая, что вы можете определить версию вашего документа, для каждой версии вашей схемы создайте XSLT, который преобразует предыдущую версию в вашу новую версию.

Вы можете применять преобразования последовательно, пока не дойдете до текущей версии.Таким образом, вы редактируете только последнюю версию документа.Конечно, вы не сможете сохранить документ в старом формате и можете разбить его на более старые версии, но это типично для многих приложений.Если вам абсолютно необходимо сохранить старую версию, просто создайте преобразование, которое идет другим путем.

Как говорит @Andy, используйте основной номер сборки вашего приложения.

Не могли бы вы добавить атрибут к корневому элементу, указывающий версию?

Таким образом, старые версии не будут взломаны, а более новые версии вашего программного обеспечения увидят этот атрибут и соответствующим образом переключатся на другой метод загрузки.

Сама нумерация версий будет зависеть от частоты вашего выпуска.Лично я бы выбрал основной номер сборки вашего программного обеспечения, если только вы не предполагаете, что формат меняется чаще, чем это.

Редактировать:только что заметил кое-что о дублировании кода:

Для этого я бы использовал Заводской шаблон, что-то вроде этого:

LoadDocument
DoNonVersionDependingLoading
VersionSpecificLoaderFactory(VersionNumber)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top