Как мне управлять различными несовместимыми формами документов на основе XML - PullRequest
5 голосов
/ 29 июля 2009

У меня есть приложение, которое сохраняет документы (документы в формате 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 или если используется более сложная стратегия (например, измененная основная редакция указывает на критические изменения, тогда как незначительные изменения редакции указывают на неразрывные изменения - например, дополнительные необязательные элементы)
  • Какой метод следует использовать для чтения самого документа и как избежать репликации огромных объемов кода для разных версий документов?
    • Хотя XPath, очевидно, является наиболее гибким, реализовать его гораздо больше, чем просто создавать классы с помощью xsd.
    • С другой стороны, если используется синтаксический анализ DOM, то для каждого критического изменения в управлении исходным кодом потребуется новая копия документа xsd, что вызывает проблемы, если когда-либо приходится применять исправления к более старым схемам (старые версии приложения все еще поддерживается).

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

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

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

Ответы [ 3 ]

4 голосов
/ 29 июля 2009

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

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

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

4 голосов
/ 29 июля 2009

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

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

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

0 голосов
/ 29 июля 2009

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

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

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

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

Для этого я бы использовал Factory Pattern, что-то вроде этого:

LoadDocument
DoNonVersionDependingLoading
VersionSpecificLoaderFactory(VersionNumber)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...