如何parsing无效的(坏的/不正确的)XML?

目前,我正在研究一个涉及parsing从其他产品收到的XML的function。 我决定对一些实际的客户数据进行一些testing,看起来另一种产品允许来自用户的input被认为是无效的。 无论如何,我仍然需要尝试找出一种parsing方法。 我们正在使用javax.xml.parsers.DocumentBuilder而且input错误如下所示。

 <xml> ... <description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></description> ... </xml> 

正如你所看到的,描述里面有一个无效的标签( <THIS-IS-PART-OF-DESCRIPTION> )。 现在,这个描述标签被认为是一个叶子标签,它不应该有任何嵌套的标签。 无论如何,这仍然是一个问题,并产生DocumentBuilder.parse(...)

我知道这是无效的XML,但它是可以预见的无效。 任何想法的方式来parsing这样的input?

这个“XML”比无效的更糟 – 它不是完整的 ; 看看格式良好与有效的XML

对违规的可预见性进行非正式评估并没有帮助。 该文本数据不是XML。 没有一致的XML工具或库可以帮助您处理它。

选项,以降低满意度的顺序:

  1. 让提供者解决他们的问题。 要求格式良好的XML。 (从技术上讲, 格式良好的XML是多余的,但对强调可能有用。)
  2. 使用宽容的标记parsing器来清理parsing之前的XML问题:

    • 独立: xmlstarlet具有强大的恢复和修复function信用: RomanPerekhrest

       xmlstarlet fo -o -R -H -D bad.xml 2>/dev/null 
    • 独立和C: HTML Tidy也适用于XML。

    • Python: 美丽的汤是基于Python的。 请参阅“ parsing器之间的差异”部分中的说明。 有关在Python中处理非格式标记的更多build议,另请参阅此问题的答案 。 另请参阅此答案以了解如何使用codecs.EncodedFile()清除非法字符。
    • Java: JSoup专注于HTML。 FilterInputStream可以用于预处理清理 。
    • 。净:

      • 可以禁用XmlReaderSettings.CheckCharacters以避开非法的XML字符问题。

      • @jdweng报告说有时可以使用XmlReader.ReadToFollowing()来解决XML语法问题 ,但是请注意下面#3中的违反规则的警告。

      • 据说Microsoft.Language.Xml.XMLParser是“容错”的。
    • PHP:请参阅DOMDocument :: $ recover和libxml_use_internal_errors(true) 。 看到很好的例子。
    • R:请参阅htmlTreeParse(),了解R中的容错标记分析。
  3. 手动使用文本编辑器或使用字符/string函数以编程方式将数据处理为文本 。 以程序化的方式执行此操作的范围可以从棘手到不可能,因为似乎常常是可预测的不是 – 规则中断很less受规则约束

    • 对于无效字符错误 ,请使用正则expression式来删除/replace无效字符:
      • PHP: preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $s);
      • Ruby: string.tr("^\u{0009}\u{000a}\u{000d}\u{0020}-\u{D7FF}\u{E000‌​}-\u{FFFD}", ' ')
      • JavaScript: inputStr.replace(/[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm, '')

一个标准的XMLparsing器将永远不会接受无效的XML,通过devise。

您唯一的select是预处理input以删除“可预测的无效”内容,或者在parsing之前将其包装在CDATA中。