【发布时间】:2010-09-12 09:35:14
【问题描述】:
我继承了一个编写不佳的 Web 应用程序,当它尝试读取存储在数据库中的带有“&”的 xml 文档时似乎有错误。例如,会有一个标签,其内容为:“预付和收费”。是否有一些秘密的简单方法可以让它在解析该字符时不会出错,或者我是否遗漏了一些明显的东西?
编辑: 是否还有其他字符会因为格式不正确而导致相同类型的解析器错误?
【问题讨论】:
标签: c# .net asp.net xml xmldocument
我继承了一个编写不佳的 Web 应用程序,当它尝试读取存储在数据库中的带有“&”的 xml 文档时似乎有错误。例如,会有一个标签,其内容为:“预付和收费”。是否有一些秘密的简单方法可以让它在解析该字符时不会出错,或者我是否遗漏了一些明显的东西?
编辑: 是否还有其他字符会因为格式不正确而导致相同类型的解析器错误?
【问题讨论】:
标签: c# .net asp.net xml xmldocument
问题是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 部分内的 & 符号。最后,它只捕获与号,而不是像更新:根据评论,我还需要更新十六进制编码 (...;) 实体的表达式。
关于哪些字符会导致问题,实际规则有点复杂。例如,数据中允许使用某些字符,但不能作为元素名称的第一个字母。并且没有简单的非法字符列表。相反,一大片(非连续的)UNICODE 是defined as legal,除此之外的任何内容都是非法的。
因此,归根结底,您必须相信您的文档来源至少具有一定程度的合规性和一致性。例如,我发现人们通常足够聪明,可以确保标签正常工作并转义 最好的办法是从源头上解决这个问题。
哦,还有关于 CDATA 建议的说明:我会用它来确保 我正在创建的 xml 格式正确,但是在处理来自外部的现有 xml 时,我发现正则表达式方法更简单。
【讨论】:
Web 应用程序没有问题,XML 文档有问题。 XML 中的 & 符号应编码为 &amp;。不这样做是语法错误。
编辑:在回答后续问题时,是的,有各种类似的错误。例如,不平衡的标签、未编码的小于号、未引用的属性值、字符编码之外的八位字节和各种 Unicode 异常、无法识别的实体引用等等。为了让任何体面的 XML 解析器使用文档,该文档必须是格式良好的。 XML 规范要求解析器遇到格式错误的文档时会抛出致命错误。
【讨论】:
其他答案都是正确的,我同意他们的建议,但让我补充一点:
请不要让应用程序使用格式不正确的 XML,这只会让我们的余生更加困难:)。
诚然,有时候,如果您无法控制另一端,您真的别无选择,但您真的应该让它抛出一个致命错误,并大声而明确地抱怨什么是坏的。发生了一个事件。
您可能会更进一步说“Ack!这个 XML 在这些地方被破坏了,由于这些原因,我尝试修复它以使其格式正确:...”。
我对 MSXML API 并不太熟悉,但大多数优秀的 XML 解析器都允许您安装错误处理程序,以便您可以捕获出现错误的确切行/列号以及获取错误代码和消息。
【讨论】:
您的数据库不包含 XML 文档。它包含一些格式良好的 XML 文档和一些在人类看来类似于 XML 的字符串。
如果可能的话,您应该修复这个问题 - 特别是,您应该修复任何生成格式错误的 XML 文档的进程。修复从这个数据库中读取数据的程序只是把墙纸放在墙上的裂缝上。
【讨论】:
你可以用&amp;替换&
或者您也可以使用CDATA 部分。
【讨论】:
有几个字符会导致 XML 数据被报告为格式错误。
来自w3schools:
像“
对于您不相信符合 XML 的输入的最佳解决方案是将其包装在 CDATA 标记中,例如
<![CDATA[This is my wonderful & great user text]]>
解析器会忽略 <![CDATA[ 和 ]]> 标记中的所有内容。
【讨论】: