18

我继承了一个编写不佳的 Web 应用程序,当它尝试读取存储在数据库中的 xml 文档时,它似乎有错误,其中包含“&”。例如,会有一个标签,其内容为:“预付和收费”。是否有一些秘密的简单方法可以让它在解析该字符时不会出错,或者我是否遗漏了一些明显的东西?

编辑:是否有任何其他字符会导致这种相同类型的解析器错误,因为格式不正确?

4

6 回答 6

41

问题是xml格式不正确。正确生成的 xml 会像这样列出这些数据:

Prepaid & Charge

我以前必须解决同样的问题,我用这个正则表达式做到了:

Regex badAmpersand = new Regex("&(?![a-zA-Z]{2,6};|#[0-9]{2,4};)");

将它与这样定义的字符串常量结合起来:

const string goodAmpersand = "&";

现在你可以说badAmpersand.Replace(<your input>, goodAmpersand);

请注意,简单String.Replace("&", "&amp;")是不够的,因为您无法提前知道给定文档的任何 & 字符是否会被正确、错误地编码,甚至两者都在同一个文档中。

这里需要注意的是,您必须在将 xml 文档加载到解析器之前对其执行此操作,这可能意味着需要额外通过它。此外,它不考虑 CDATA 部分内的 & 符号。最后,它只捕获 & 符号,而不捕获其他非法字符,如 <。 更新:根据评论,我还需要更新十六进制编码 (&#x...;) 实体的表达式。

关于哪些字符会引起问题,实际规则有点复杂。例如,数据中允许使用某些字符,但不能作为元素名称的第一个字母。并且没有简单的非法字符列表。相反,一大片(不连续的) UNICODE 被定义为合法的,除此之外的任何东西都是非法的。

因此,归根结底,您必须相信您的文档来源至少具有一定程度的合规性和一致性。例如,我发现人们通常足够聪明,可以确保标签正常工作并转义 <,即使他们不知道 & 是不允许的,因此你今天遇到了问题。但是,最好的办法是从源头上解决这个问题。

哦,还有关于 CDATA 建议的说明:我会用它来确保我正在创建的 xml 格式正确,但是在从外部处理现有 xml 时,我发现 regex 方法更容易。

于 2008-09-23T14:54:17.667 回答
4

Web 应用程序没有问题,XML 文档有问题。XML 中的 & 符号应编码为&amp;. 不这样做是语法错误。

编辑:在回答后续问题时,是的,有各种类似的错误。例如,不平衡的标签、未编码的小于号、未引用的属性值、字符编码之外的八位字节和各种 Unicode 异常、无法识别的实体引用等等。为了让任何体面的 XML 解析器使用文档,该文档必须是格式良好的。XML 规范要求解析器遇到格式错误的文档时会引发致命错误。

于 2008-09-23T14:54:49.863 回答
4

其他答案都是正确的,我同意他们的建议,但让我补充一点:

请不要让应用程序使用非格式良好的 XML,它只会让我们的余生更加困难 :)。

诚然,有时候如果你无法控制另一端,你真的别无选择,但你真的应该让它抛出一个致命错误,并大声而明确地抱怨发生此类事件时发生了什么问题.

您可能会更进一步说“Ack!这个 XML 在这些地方被破坏了,由于这些原因,我尝试修复它以使其格式正确:...”。

我对 MSXML API 并不太熟悉,但大多数优秀的 XML 解析器都允许您安装错误处理程序,以便您可以捕获出现错误的确切行/列号以及获取错误代码和消息。

于 2008-09-23T15:18:58.823 回答
3

您的数据库不包含 XML 文档。它包含一些格式良好的 XML 文档和一些在人类看来类似于 XML 的字符串。

如果可能的话,您应该解决这个问题 - 特别是,您应该修复生成格式错误的 XML 文档的任何进程。修复从该数据库中读取数据的程序只是将墙纸放在墙上的裂缝上。

于 2008-09-23T20:52:56.260 回答
2

您可以将 & 替换为&amp;

或者您也可以使用CDATA部分。

于 2008-09-23T14:53:24.517 回答
2

有几个字符会导致 XML 数据被报告为格式错误。

来自w3schools

“<”和“&”之类的字符在 XML 元素中是非法的。

对于您不能相信符合 XML 的输入的最佳解决方案是将其包装在 CDATA 标记中,例如

<![CDATA[This is my wonderful & great user text]]>

解析器会忽略<![CDATA[and标记中的所有内容。]]>

于 2008-09-23T14:57:36.707 回答