5

我有一个应用程序,它以基于 Xml 的格式保存文档(想想 word 文档) - 目前从 xsd 文件生成的 C# 类用于读取/写入文档格式,直到最近我不得不更改格式时一切都很好文件。我担心的是向后兼容性,因为我的应用程序的未来版本 需要能够读取所有以前版本保存的文档,理想情况下,我还希望我的应用程序的旧版本能够优雅地处理阅读我的应用程序未来版本保存的文档。

例如,假设我更改文档的架构以在某处添加(可选)额外元素,那么我的应用程序的旧版本将简单地忽略额外的元素并且不会有任何问题:

<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 的新副本,如果需要将修复应用于旧模式,则会导致问题(仍然支持旧版本的应用程序) .

此外,我假设我所做的所有更改都可以分为“喙状更改”和“非破坏性更改”这两类,但我并不完全相信这是一个安全的假设。制作。

请注意,我非常松散地使用术语“文档” - 内容根本不像文档!

谢谢你能给我的任何建议。

4

3 回答 3

4

XSLT 是一个明显的选择。鉴于您可以识别文档的版本,对于您的模式的每个版本,创建一个 XSLT 将以前的版本转换为新版本。

您可以按顺序应用转换,直到达到当前版本。因此,您只需要编辑最新的文档版本。当然,您将无法保存为旧格式,并且可以破坏旧版本的文档,但这是许多应用程序的典型情况。如果您绝对需要保存到旧版本,只需创建一个相反的转换。

就像@Andy 所说,使用您的应用程序的主要版本号。

于 2009-07-29T16:18:39.397 回答
4

您肯定需要 XML 文件中的版本号,我建议不要将其与应用程序的版本绑定,因为它实际上是一个单独的实体。您可以通过应用程序的两个或三个版本而无需更改 XML 格式,或者您可能会在开发单个版本期间多次更改格式。

如果您希望旧版本的应用程序能够读取新版本的 XML 文件,那么您永远不能删除元素或更改它们的名称。您总是可以添加元素,旧代码会很乐意忽略它们(XML 的一个很好的特性),但是如果您删除它们,那么旧代码将无法运行。

就像 Ishmael 所说,XSLT 是一种将 XML 格式从一个版本转换为另一个版本的好方法,这样您就不会在源代码中遇到一大堆解析例程。

于 2009-07-29T16:36:39.667 回答
0

您可以向指定版本的根元素添加一个属性吗?

这样旧版本就不会被破坏,而新版本的软件将看到该属性并适当地切换到不同的加载方法。

版本编号本身取决于您的发布频率。我个人会使用您软件中的主要版本号,除非您预见到格式的变化比这更频繁。

编辑:刚刚注意到关于代码重复的一点:

为此,我将使用工厂模式,如下所示:

LoadDocument
DoNonVersionDependingLoading
VersionSpecificLoaderFactory(VersionNumber)
于 2009-07-29T15:28:16.703 回答