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