Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何管理基于Xml的文档的不同不兼容格式_C#_Xml_Xsd_Schema_Xmldocument - Fatal编程技术网

C# 如何管理基于Xml的文档的不同不兼容格式

C# 如何管理基于Xml的文档的不同不兼容格式,c#,xml,xsd,schema,xmldocument,C#,Xml,Xsd,Schema,Xmldocument,我有一个应用程序,它以基于Xml的格式保存文档(比如word文档)——目前从xsd文件生成的C#类用于读取/写入文档格式,直到最近我不得不更改文档格式时,一切都很好。我关心的是向后兼容性,因为我的应用程序的未来版本需要能够阅读所有以前版本保存的文档,理想情况下,我还希望我的应用程序的旧版本能够优雅地处理阅读我的应用程序未来版本保存的文档 例如,假设我更改文档的模式以在某处添加一个(可选)额外元素,那么我的应用程序的旧版本将忽略额外元素,并且不会出现任何问题: <doc> &l

我有一个应用程序,它以基于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>

12
13
为了避免将来的支持难题,我想提出一个体面的策略来处理我将来可能进行的更改,以便我现在发布的应用程序版本能够在将来应对这些更改:

  • 文档的“版本号”应该存储在文档本身中吗?如果是,应该使用什么版本控制策略?文档版本是否与.exe程序集版本匹配,或者是否应使用更复杂的策略(例如,主要版本更改表示中断更改,而次要版本增量表示非中断更改-例如额外的可选元素)
  • 我应该使用什么方法来阅读文档本身,如何避免为不同版本的文档复制大量代码?
    • 尽管XPath显然是最灵活的,但它的实现比简单地用xsd生成类要复杂得多
    • 另一方面,如果使用DOM解析,那么在源代码管理中,每次中断的更改都需要一个新的文档xsd副本,如果需要将修复应用于旧模式(仍支持旧版本的应用程序),则会导致问题
此外,我在假设我所做的所有更改都可以分为两类,即“尖刻更改”和“非破坏性更改”,但我并不完全相信这是一个安全的假设

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


感谢您提供的任何建议。

您能为根元素添加一个属性来指定版本吗

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

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

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

为此,我将使用工厂模式,类似于这样:

LoadDocument
DoNonVersionDependingLoading
VersionSpecificLoaderFactory(VersionNumber)

XSLT在这里显然是一种选择。假设您可以识别文档的版本,那么对于模式的每个版本,创建一个XSLT,将以前的版本转换为新版本

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


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

您肯定需要XML文件中的版本号,我建议不要将其绑定到应用程序的版本,因为它实际上是一个单独的实体。您可以在不更改XML格式的情况下浏览应用程序的两个或三个版本,也可以在开发单个版本的过程中多次更改格式

如果希望较旧版本的应用程序能够读取较新版本的XML文件,则永远不能删除元素或更改其名称。您总是可以添加元素,旧代码会很高兴地忽略它们(XML的一个很好的特性),但是如果您删除它们,旧代码将无法正常工作


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

完全同意这个观点XSLT是您的朋友,这样您可以创建一个XSL,只需对文档进行足够的修改,就可以使其达到该版本的已知状态。你可以为每个版本切换加载它们,然后在你的源代码管理中,你只需要将XSL存储在每个格式更改中,就像Rudy on Rails中的迁移一样。我同意XSLT是一种巧妙的方法,但我不会将XML格式的版本与应用程序的版本号绑定在一起(我的推理请参见我的答案)。@17/26是正确的,对于某些补丁和临时版本,您将直接需要新版本,而不必每个主要版本都需要一个。