使用字符串连接构建XML有什么坏处?

在线程什么是你最喜欢的“程序员无知”宠儿? ,出现以下答案,有大量的赞成票:

Programmers who build XML using string concatenation.

我的问题是,为什么通过字符串连接构建XML(例如C#中的StringBuilder )不好?

我过去曾多次这样做过,因为对于我正在使用的数据结构/对象来说,它有时是从A点到B点的最快捷方式。 到目前为止,我提出了一些原因,为什么这不是最好的方法,但有什么我忽略的? 为什么要避免这种情况?

  1. 可能我能想到的最大原因是你需要手动转义字符串,大多数新程序员(甚至是一些有经验的程序员)都会忘记这一点。 它们在测试时对它们很有用,但是当有人在某个地方输入一个&符号时,“随机”他们的应用程序将会失败。 好的,我会买这个,但是很容易防止这个问题( SecurityElement.Escape命名一个)。
  2. 当我这样做时,我通常省略XML声明(即 )。 这有害吗?
  3. 绩效惩罚? 如果坚持使用正确的字符串连接(即StringBuilder ),这是否需要关注? 据推测,像XmlWriter这样的类也需要做一些字符串操作……
  4. 有更优雅的生成XML的方法,例如使用XmlSerializer自动序列化/反序列化类。 好的,我同意。 C#有很多有用的类,但有时我不想为一些非常快速的类创建类,比如写出日志文件或其他东西。 这只是我懒惰吗? 如果我正在做一些“真实”的事情,这是我处理w / XML的首选方法。

你最终可能会得到无效的XML,但在你再次解析它之前你不会发现 – 然后就太晚了。 我经过惨痛的教训才学到这个。

我认为可读性,灵活性和可扩展性是重要因素。 考虑下面的Linq-to-Xml:

 XDocument doc = new XDocument(new XDeclaration("1.0","UTF-8","yes"), new XElement("products", from p in collection select new XElement("product", new XAttribute("guid", p.ProductId), new XAttribute("title", p.Title), new XAttribute("version", p.Version)))); 

你能找到比这更容易的方法吗? 我可以将它输出到浏览器,将其保存到文档,在几秒钟内添加属性/元素等等……只需添加几行代码即可。 我可以毫不费力地用它做几乎所有事情。

实际上,我发现字符串连接的最大问题不是第一次正确,而是在代码维护期间保持正确。 通常,使用字符串concat完美编写的XML片段会更新以满足新的要求,并且字符串连接代码太脆弱了。

只要替代方案是XML序列化和XmlDocument ,我就可以看到simple参数支持string concat。 但是,自从XDocument等。 也就是说,没有理由再使用string concat来构建XML了。 有关编写XML的最佳方法,请参阅Sander的答案。

XDocument另一个好处是XML实际上是一个相当复杂的标准,大多数程序员根本就不理解它。 我目前正在处理一个向我发送“XML”的人,包括不带引号的属性值,缺少结束标记,不正确的区分大小写以及不正确的转义。 但是因为IE接受它(作为HTML),它必须是正确的! 叹息……无论如何,重点是字符串连接可以让你写任何东西,但XDocument将强制符合标准的XML。

我在2006年写了一篇关于字符串连接生成的XML的博客文章。 简单的一点是,如果XML文档无法validation(编码问题,命名空间问题等), 那么它不是XML也不能被视为XML

我已经看到XML文档的多个问题可以直接归因于使用字符串连接手动生成XML文档,并且几乎总是围绕正确使用编码。

问问自己这个; 我目前使用什么字符集编码我的文档(’ascii7’,’ibm850’,’iso-8859-1’等)? 如果我将UTF-16字符串值写入已手动声明为“ibm850”的XML文档,会发生什么?

鉴于.NET中使用XmlDocument的XML支持的丰富性,现在尤其是XDocument,在基本的字符串连接IMHO中不必使用这些库是一个非常引人注目的论点。

我认为问题在于您不是将xml文件视为逻辑数据存储事物,而是将其作为编写字符串的简单文本文件。

显而易见,这些库为您执行字符串操作,但读取/写入xml应该类似于将数据保存到数据库或逻辑上类似的东西

如果你需要简单的XML,那就没关系。 当xml变得更大或更复杂时,它只是字符串连接的可维护性破坏了。 您在开发时或维护时付款。 您的选择始终是您的 – 但历史表明维护总是更昂贵,因此任何使其更容易的事情通常都是值得的。

您需要手动转义字符串。 那就对了。 但这就是全部吗? 当然,您可以将XML规范放在桌面上,并在每次构建XML字符串时考虑每个可能的角落情况时仔细检查。 或者您可以使用封装此知识的库…

反对使用字符串连接的另一点是,在读取代码时,数据的层次结构不明确。 例如,在@ Sander的Linq-to-XML示例中,“product”元素属于哪个父元素,“title”属性应用于哪个元素等等。

wsanville,它的态度和你一样,为什么我们要花这么多时间来重构那些难以维护且无法重用的可怕代码。

“快速从A点到B点”。 然后你必须改变一些东西……

不,谢谢,不是我的团队。

正如您所说,使用字符串连接构建XML是很尴尬的,特别是现在您拥有XML linq,它允许简单构建XML图形并获得名称空间等。

显然上下文以及如何使用它很重要,例如在日志示例string.Format中可以完全接受。

但是,当使用复杂的XML图并只使用StringBuilder时,人们常常忽略这些替代方案。

主要原因是干:不要重复自己。

如果使用string concat来执行XML,则将不断重复将字符串保留为有效XML文档的函数。 所有validation都将重复或不存在。 最好依赖于包含XMLvalidation的类。

也许它永远不会发生,但是如果你的环境有一天会切换到XML 2.0呢? 您的字符串连接的XML在新环境中可能有效,也可能无效,但XDocument几乎肯定会做正确的事情。

好的,这是一个范围,但特别是如果您的不符合标准的XML没有指定XML版本声明……只是说。

我总是发现创建一个XML比阅读其中一个更多的苦差事。 我从来没有得到序列化的支持 – 它似乎永远不适用于我的类 – 而不是花费一周时间试图让它工作,我可以在很短的时间内使用字符串创建一个XML文件并编写它出。

然后我使用XMLReader树加载它。 如果XML文件读取不是有效的,我会返回并在保存例程中找到问题并进行更正。 但是在我得到一个有效的保存/加载系统之前,我拒绝执行关键任务工作,直到我知道我的工具是可靠的。

我想这归结于程序员的偏好。 当然,有不同的做事方式,当然,但对于开发/测试/研究/调试,这没关系。 但是,在将其交给另一位程序员之前,我还会清理我的代码并对其进行评论。

因为无论你使用StringBuilder或XMLNodes来保存/读取你的文件, 如果它都是乱七八糟的混乱,没有人会理解它是如何工作的。