修复错误的 XML 文件(例如,未转义等)[重复]

Posted

技术标签:

【中文标题】修复错误的 XML 文件(例如,未转义等)[重复]【英文标题】:Fixing bad XML file (eg. unescaped & etc.) [duplicate] 【发布时间】:2011-08-26 12:09:28 【问题描述】:

我从第 3 方获得了一个 XML 文件,我必须在我的应用程序中导入该文件,并且 XML 在内部文本中有未转义 & 的元素,他们不会解决这个问题!所以我的问题是处理这个问题的最佳方法是什么?

这个 XML 非常大,而且修复速度必须很快,我的第一个解决方案是用 & 符号替换 & 字符,但出于显而易见的原因,我真的不喜欢这个“解决方案”。我不知道如何将 XmlStringReader 与此类 XML 一起使用,因为在此类行上会引发异常,因此我不能在内部文本上使用 htmlEncode。我试图将 XmlTextReader Settings.CheckCharacters 设置为 false 但没有结果。

这是示例,& 在元素中,并且在该字段中可以是某些公司名称中的任何内容,因此我的替换修复可能不适用于其他公司名称,我想以某种方式使用 HtmlEncode ,但当然仅限于内部文本。

<komitent ID="001398">
  <sifra>001398</sifra>
  <redni_broj>001398</redni_broj>
  <naziv>LJUBICA & ŽARKO</naziv>
  <adresa1>Odvrtnica 27</adresa1>
  <adresa2></adresa2>
  <drzava>HRVATSKA</drzava>
  <grad>Zagreb</grad>
</komitent>

【问题讨论】:

切换第 3 方 :-) 老实说,如果该方无法提供有效的 XML,我会强烈重新考虑使用它。 @Darin,我会真的真的喜欢这样做,但不幸的是这不是一个选择:( @Antonio Bakula,在这种情况下,您最好的选择是字符串/替换,希望您已经涵盖了该 XML 可能被破坏的所有可能情况。我的意思是,如果 XML 无效,您可能无法知道它在哪里被破坏,因此您不能依赖 XML 解析器。今天它是一个损坏的 & 符号,明天它是一个缺失的结束 &gt; 和缺失结束标签的第二天。你明白我的意思吗?修复损坏的最佳方法是一开始就不要损坏它。 @Antonio Bakula,您需要了解的是您没有 XML 文件。你有一个纯文本文件。因此,如果未定义此文件的格式,您将需要手动解析它。这就是为什么人们创建像 XML 这样的格式并为它们定义标准的原因。因此,如果第 3 方无法为您提供 XML 文件,至少请他们定义他们提供给您的文本文件的格式,以便您必须编写的解析器尽可能可靠,或者请他们为您提供使用此自定义格式的解析器。 当然,第 3 方无法修复 XML:这将破坏其客户实施的所有变通办法! 【参考方案1】:

下面的关键信息是,除非您知道输入文件的确切格式,并保证与 XML 的任何偏差都是一致的,否则您无法以编程方式修复而不冒修复错误的风险。

通过将&amp;amp; 替换为&amp;amp; 来修复它是一个可接受的解决方案,当且仅当:

    这些数据没有可接受的格式良好的来源。

    作为@Darin Dimitrov cmets,请尝试寻找更好的提供商,或让该提供商修复它。 JSON(例如)比格式不正确的 XML 更可取,即使您不使用 javascript

    这是一次性(或至少非常罕见)的导入。

    如果您必须在运行时获取它,那么此解决方案将不起作用。

    您可以不断迭代,为其设计新的修复程序,为遇到的每个问题添加解决方案。

    您可能会发现,一旦通过转义&amp;amp; 字符“修复”了它,就会出现其他错误。

    您有资源手动检查“固定”数据的完整性。

    您“修复”的错误可能比您意识到的更微妙。

    文档中没有格式正确的实体 -

    简单地将&amp;amp; 替换为&amp;amp; 将错误地将&amp;amp;quot; 更改为&amp;amp;quot;。您也许可以解决这个问题,但不要天真地认为它可能有多么棘手(实体可能在 DTD 中定义,可能引用 unicode 代码点...)

    1234563 /p>

【讨论】:

【参考方案2】:

从改变你的心态开始。输入不是 XML,所以不要称它为 XML。甚至不要使用“xml”来标记您的问题。它不是 XML 的事实意味着您不能对它使用任何 XML 工具,也无法获得 XML 数据交换的任何好处。您正在处理一种没有规范且没有任何工具的专有格式。像对待任何其他专有格式一样对待它 - 尝试发现你所获得的规范,并为它编写一个解析器。

【讨论】:

你能写出或者推荐一个解析器来做我们都知道它应该做的事情吗?如果&amp;amp; 所在的位置无法使用未转义的&amp;amp;,并且&amp;amp; 不会导致有效的实体引用,请将&amp;amp; 替换为&amp;amp; 我可以编写这样的解析器,但我不会。我碰巧认为 XML 通过说应该拒绝无效的转义序列做出了正确的决定。验证传入 XML 的任何松懈只会鼓励生成 XML 的人更加松懈,并且很快就会有一些人根本不费心转义特殊字符,这意味着当您遇到有效的转义序列时会更加困惑不知道是否需要转义。 严格一点就好。但是现在我,就像问这个问题的人一样,有一个问题。地球上没有文本编辑器可以打开一个 4.2GB 的文件。即使它可以,有数百万个无效条目,我有一个如何解决它的编程问题。当然是一个值得 *** 的问题。 当然这是一个有价值的问题,我试图给出一个有价值的答案。【参考方案3】:

如果您知道文件的标签并希望“确定”标签内可能包含可疑数据的文本,您可以执行以下操作:

private static string FixBadXmlText(string xmlText)
           
    var unreliableTextTags = new[]  "message", "otherdata", "stacktrace", "innerexception" ;

    foreach(var tag in unreliableTextTags)
    
        string openTag = "<" + tag + ">";
        string closeTag = "</" + tag + ">";
        xmlText = xmlText.Replace(openTag, openTag + "<![CDATA[").Replace(closeTag, "]]>" + closeTag);
    

    return xmlText;

CDATA Section (&lt;![CDATA[ your text here ]]&gt;) 中的任何内容都不会被 XML 解析器解释,因此不需要转义。当我想要解析一些没有正确转义输入的糟糕的 XML 时,这对我很有帮助。

【讨论】:

【参考方案4】:

由于您的起始 XML 是错误的,因此您不能使用任何 XmlReader,因为它们无法正确读取它。

如果只有 XML 节点的值不是 htmlEncoded,那么您就必须手动读取行、解析(获取 xml 节点名称及其值)、编码并输出到新文件。

我们经常会遇到类似的情况,所以我理解您的痛苦 - 但大多数情况下,错误都有一些“规则”,所以我猜这里他们没有编码公司名称(也许街道名称),因此您可以只搜索该字符串 &lt;naziv&gt;,它是结束标签 &lt;/naziv&gt; 和 HtmlEncode 之间的所有内容。还有,因为是企业名,所以不会有换行,可以让你的生活轻松不少……

【讨论】:

【参考方案5】:

您可以根据结构的复杂程度尝试使用正则表达式:

Regex mainSplitter = new Regex("<komitent ID=\"([0-9]*)\">(.*?)</komitent>");
Regex nazivFinder = new Regex("<naziv>(.*?)</naziv>");

foreach (Match item in mainSplitter.Matches(test))

    Console.WriteLine(item);

    string naziv = null;

    Match node = nazivFinder.Match(item.Groups[2].Value);
    if (node != null)
        naziv = node.Groups[1].Value;

【讨论】:

【参考方案6】:

您可以将文件作为 XPL 处理,甚至可以使用 XPL 解析器将此类文件转换为有效的 XML。 XPL(可扩展过程语言)与 XML 类似,但解析器允许在文本字段中使用 XML 的“特殊字符”。因此,您实际上可以通过 XPL 进程运行无效的 XML 文件(由于特殊字符而无效)。在某些情况下,您可以使用 XPL 处理器而不是 XML 处理器。您还可以使用它来预处理无效文件,而不会造成任何性能损失。 Artificial Intelligence, XML, and Java Concurrency

【讨论】:

以上是关于修复错误的 XML 文件(例如,未转义等)[重复]的主要内容,如果未能解决你的问题,请参考以下文章

sql 转义单引号 - 修复:错误:105字符串后面的未闭合引号

如何转义xml中的特殊字符

XML中必须进行转义的字符

OracleWebRowSet writeXml 方法无法转义特殊字符,例如 &

xml文件中的错误(android编程):未绑定前缀[重复]

使用 XML 库解析未转义的 HTML 并检索标记值