Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何解析无效(错误/格式不正确)的XML?_Java_Xml_Xml Parsing_Xml Validation - Fatal编程技术网

Java 如何解析无效(错误/格式不正确)的XML?

Java 如何解析无效(错误/格式不正确)的XML?,java,xml,xml-parsing,xml-validation,Java,Xml,Xml Parsing,Xml Validation,目前,我正在开发一个功能,它涉及解析我们从另一个产品收到的XML。我决定对一些实际的客户数据运行一些测试,而另一个产品似乎允许用户输入应该被视为无效的数据。不管怎么说,我还是要想办法解析它。我们使用的是javax.xml.parsers.DocumentBuilder,输入时出现如下错误 <xml> ... <description>Example:Description:<THIS-IS-PART-OF-DESCRIPTION></descri

目前,我正在开发一个功能,它涉及解析我们从另一个产品收到的XML。我决定对一些实际的客户数据运行一些测试,而另一个产品似乎允许用户输入应该被视为无效的数据。不管怎么说,我还是要想办法解析它。我们使用的是
javax.xml.parsers.DocumentBuilder
,输入时出现如下错误

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

...
示例:说明:
...
正如您所知,描述中似乎有一个无效的标记(
)。现在,这个描述标签是一个叶子标签,里面不应该有任何嵌套的标签。无论如何,这仍然是一个问题,并在
DocumentBuilder.parse(…)


我知道这是无效的XML,但可以预见它是无效的。关于解析这种输入的方法有什么想法吗?

根据设计,标准XML解析器永远不会接受无效的XML

您唯一的选择是在解析之前对输入进行预处理,以删除“可预测的无效”内容,或者将其包装在CDATA中

认为“XML”比无效更糟糕——它的格式不好;请参见

对违法行为的可预测性进行非正式评估无济于事。该文本数据不是XML。没有一致的XML工具或库可以帮助您处理它

选项,首先是最理想的:
  • 让提供商解决他们端的问题要求格式良好的XML。(从技术上讲,格式良好的XML是多余的,但可能有助于强调。)

  • 在解析为XML之前,请使用容错标记解析器清除问题:

    • 单机版:具有强大的恢复和修复功能信贷:

    • 单机版和C/C++:也适用于XML。是TangSuffic到C++的端口。
    • Python:是基于Python的。请参见本节中的注释。有关更多信息,请参见 处理Python中格式不正确的标记的建议, 尤其包括。 有关如何使用
      codecs.EncodedFile()
      清除非法字符,请参见

    • Java:并关注HTML。可用于

    • .NET:

      • 能 被禁用以克服非法XML字符问题
      • 可以设置为 这样就可以读取缺少根元素的内容
      • 有时也会这样 习惯,但注意 下面第3条中的违规警告
      • 被称为“容错”
    • PHP:请参阅和。看一个很好的例子

    • Ruby:Nokogiri支持“”

    • R:有关R中的容错标记解析,请参阅

    • Perl:请参阅“一个超级自由的XML解析器,可以解析破碎的XML。”

  • 使用文本编辑器或 以编程方式使用字符/字符串函数。这样做 从编程角度来看,可以是棘手的,也可以是不可能的 看起来是什么 可预测性通常是不可预测的--违反规则很少受规则约束

    • 对于无效字符错误,请使用正则表达式删除/替换无效字符:

      • preg\u replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u',''$s)
      • string.tr(“^\u{0009}\u{000a}\u{000d}\u{0020}-\u{D7FF}\u{E000‌​}-\u{FFFD},'')
      • inputStr.replace(/[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm',)
    • 对于符号,使用正则表达式将匹配项替换为
      :credit:

  • 请注意,上面的正则表达式不接受注释或CDATA
    应考虑各节。

    在IMO中,这些情况应通过使用解决

    下面不是这个具体案例的真正答案,但找到了(多亏了Coderwall上的inuyasha82)。在处理格式错误的XML时,这个代码位确实激发了我处理另一个类似问题的灵感,所以我在这里分享它

    请不要编辑下面的内容,因为它是在原来的网站上

    XML格式要求文档中声明的唯一根元素有效。 例如,有效的xml是:

    <root>
         <element>...</element>
         <element>...</element>
    </root>
    
    然后打开一个FileInputStream:

    FileInputStream fis = new FileInputStream(file);
    
    如果我们试图在此时使用任何XML库解析此流,我们将引发格式错误的文档异常

    现在,我们创建一个包含三个元素的InputStream对象列表:

    包含字符串“”的ByteInputStream元素 我们的FileInputStream 字符串为“”的ByteInputStream 因此,代码是:

    List<InputStream> streams = 
        Arrays.asList(
            new ByteArrayInputStream("<root>".getBytes()),
        fis,
        new ByteArrayInputStream("</root>".getBytes()));
    

    现在,我们可以在cntr上使用任何XML解析器库,它将被解析而不会出现任何问题。(使用Stax库进行检查);

    公认的答案是很好的建议,并且包含非常有用的链接

    我想补充一点,使用SGML(HTML和XML的ISO标准超集)可以修复这种情况,以及格式不正确和/或DTD无效的XML。在您的情况下,有效的方法是将伪
    this-is-PART-of-DESCRIPTION
    元素声明为SGML空元素,然后使用
    osx
    程序(OpenSP/OpenJade SGML包的一部分)将其转换为XML

    <!DOCTYPE xml [
      <!ELEMENT xml - - ANY>
      <!ELEMENT description - - ANY>
      <!ELEMENT THIS-IS-PART-OF-DESCRIPTION -  - EMPTY>
    ]>
    <xml>
      <description>blah blah
        <THIS-IS-PART-OF-DESCRIPTION>
      </description>
    </xml>
    
    
    ]>
    废话
    
    它将输出格式良好的XML,以便使用您选择的XML工具进行进一步处理

    但是,请注意,您的示例代码段还有另一个问题,即以字母
    xml
    xml
    xml
    等开头的元素名称是保留在xml中的,并且不会被符合要求的xml解析器接受。

    无效的xml实际上不是xml。但是,存在期望xml有效的解析器
    File file = new File(pathtofile);
    
    FileInputStream fis = new FileInputStream(file);
    
    List<InputStream> streams = 
        Arrays.asList(
            new ByteArrayInputStream("<root>".getBytes()),
        fis,
        new ByteArrayInputStream("</root>".getBytes()));
    
    InputStream cntr = 
    new SequenceInputStream(Collections.enumeration(str));
    
    <!DOCTYPE xml [
      <!ELEMENT xml - - ANY>
      <!ELEMENT description - - ANY>
      <!ELEMENT THIS-IS-PART-OF-DESCRIPTION -  - EMPTY>
    ]>
    <xml>
      <description>blah blah
        <THIS-IS-PART-OF-DESCRIPTION>
      </description>
    </xml>