将带有“&”的 XML 读入 C# XMLDocument 对象
Posted
技术标签:
【中文标题】将带有“&”的 XML 读入 C# XMLDocument 对象【英文标题】:Reading XML with an "&" into C# XMLDocument Object 【发布时间】:2010-09-12 09:35:14 【问题描述】:我继承了一个编写不佳的 Web 应用程序,当它尝试读取存储在数据库中的带有“&”的 xml 文档时似乎有错误。例如,会有一个标签,其内容为:“预付和收费”。是否有一些秘密的简单方法可以让它在解析该字符时不会出错,或者我是否遗漏了一些明显的东西?
编辑: 是否还有其他字符会因为格式不正确而导致相同类型的解析器错误?
【问题讨论】:
【参考方案1】:问题是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 时,我发现正则表达式方法更简单。
【讨论】:
十六进制编码 ...;也可能存在字符引用。我建议首先尝试正常解析文档,如果结果格式正确,则仅尝试应用修复黑客。这样您就可以确定以后修复的有效文档将始终正常工作。【参考方案2】:Web 应用程序没有问题,XML 文档有问题。 XML 中的 & 符号应编码为 &amp;
。不这样做是语法错误。
编辑:在回答后续问题时,是的,有各种类似的错误。例如,不平衡的标签、未编码的小于号、未引用的属性值、字符编码之外的八位字节和各种 Unicode 异常、无法识别的实体引用等等。为了让任何体面的 XML 解析器使用文档,该文档必须是格式良好的。 XML 规范要求解析器遇到格式错误的文档时会抛出致命错误。
【讨论】:
所以,您认为我可以将责任归咎于我的懒惰集成团队发送错误的 XML 是吧?有些东西告诉我,我仍然可以在我这边解决它。 :-( 如果可能的话,是的,从源头上解决问题。如果您绝对必须处理无法修复系统的坏源,请尝试在它进入数据库之前对其进行修复。【参考方案3】:其他答案都是正确的,我同意他们的建议,但让我补充一点:
请不要让应用程序使用格式不正确的 XML,这只会让我们的余生更加困难:)。
诚然,有时候,如果您无法控制另一端,您真的别无选择,但您真的应该让它抛出一个致命错误,并大声而明确地抱怨什么是坏的。发生了一个事件。
您可能会更进一步说“Ack!这个 XML 在这些地方被破坏了,由于这些原因,我尝试修复它以使其格式正确:...”。
我对 MSXML API 并不太熟悉,但大多数优秀的 XML 解析器都允许您安装错误处理程序,以便您可以捕获出现错误的确切行/列号以及获取错误代码和消息。
【讨论】:
我倾向于同意。我的第一个行动是抱怨,我会看看他们是否会解决它。问题是我的解决方法是 2 分钟,而他们的解决方法更多。无论如何感谢您的建议。 +1。如果你修复它,至少继续发出警告。继续以“错误的方式”进行操作,您最终肯定会遇到破坏您正在采取的任何修复措施的数据。【参考方案4】:您的数据库不包含 XML 文档。它包含一些格式良好的 XML 文档和一些在人类看来类似于 XML 的字符串。
如果可能的话,您应该修复这个问题 - 特别是,您应该修复任何生成格式错误的 XML 文档的进程。修复从这个数据库中读取数据的程序只是把墙纸放在墙上的裂缝上。
【讨论】:
【参考方案5】:你可以用&amp;
替换&
或者您也可以使用CDATA 部分。
【讨论】:
全局编码 & 将丢失数据中的任何真实实体引用。【参考方案6】:有几个字符会导致 XML 数据被报告为格式错误。
来自w3schools:
像“
对于您不相信符合 XML 的输入的最佳解决方案是将其包装在 CDATA 标记中,例如
<![CDATA[This is my wonderful & great user text]]>
解析器会忽略 <![CDATA[
和 ]]>
标记中的所有内容。
【讨论】:
也许澄清一下'CDATA标签中除了结束标签之外的所有东西都被解析器忽略了? 并非全部.. ]]> 不是。这意味着,如果他发送了一个包含 CDATA 部分的 xml,甚至只是一个 ]]> 文本块,它就会中断。 如果您在输入中遇到 ]]>,请将您的输入分成 2 个 CDATA 部分:一个以 ]] 结尾,一个以 > 开头。解析器将再次重新连接这两个部分。以上是关于将带有“&”的 XML 读入 C# XMLDocument 对象的主要内容,如果未能解决你的问题,请参考以下文章
将带有嵌套标签的 XML 读入 Spark RDD,并转换为 JSON