如何跳过xml标记内的文本验证?

时间:2018-05-18 07:31:27

标签: java xml parsing xsd xml-parsing

我以这种格式从bugzilla下载xml:

<bugzilla>
     <bug>
          <bug_id>111</bug_id>
          <short_desc>text 1 & 2</short_desc>
      </bug>
      <bug>
          <bug_id>222</bug_id>
          <short_desc>text 2 <this is a short desc> </short_desc>
     </bug>
</bugzilla>

正如您所看到的,当我尝试使用jaxb解析器解析它时,它失败有两个原因:

  1. for&amp;在第一个标记内(需要更改为&amp; 错误消息:The entity name must immediately follow the '&' in the entity reference.

  2. <this is a short desc>文字的相同案例。错误消息The entity name must immediately follow the '&' in the entity reference.

  3. 但我不明白的是这些都是有效标签的内容。那么为什么验证逻辑正在运行这样的内容。在第二种情况下,它不仅仅是<thisisashortdesc>的单个标记,它可以抛出实际的有效错误,表示缺少结束标记。但是这种情况之间有空格。

    找到下面使用的代码:

    文件文件=新文件(&#34; C:\ test \ file.xml&#34;);

        JAXBContext jaxbContext = JAXBContext.newInstance(Bugzilla.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Bugzilla bugzillaReport = (Bugzilla) jaxbUnmarshaller.unmarshal(file);
    

    无论如何都要解决这个问题。

1 个答案:

答案 0 :(得分:1)

如您所知,必须解析有效的XML,因为HTML中没有模糊匹配。标准解决方案是放置<![CDATA[....]]>。 ( CDATA 代表字符数据。)

<short_desc><![CDATA[text 1 & 2]]></short_desc>
<short_desc><![CDATA[text 2 <this is a short desc> ]]></short_desc>

这很麻烦,问题是当预期文本而不是CData时,使用是否仍然有效。并且创建正确的XML可能更容易。为此目的,Apache commons还有一个StringEscapeUtils.escapeXml10(String)

首先尝试(CDATA)。

String xml = new String(Files.readAllBytes(Paths.get("C:\\test\\file.xml")),
         StandardCharsets.UTF_8);
xml = "<?xml version=\"1.0\">\n" + xml;
xml = xml.replace("<short_desc>", "<short_desc><![CDATA[");
xml = xml.replace("</short_desc>", "]]></short_desc>");
jaxbUnmarshaller.unmarshal(new StreamSource(new StringReader(xml)));

请注意,反斜杠\必须在java String中自动转义。

java 9修复:

xml = xml.replaceAll("(?s)<short_desc>(.*)</short_desc>",
        matchResult -> "<short_desc>"
                       + StringEscapeUtils.escapeXml10(matchResult.group(1))
                       + "</short_desc>");

或没有apache常见语言StringEscapeUtils:

xml = xml.replaceAll("(?s)<short_desc>(.*)</short_desc>",
        matchResult -> "<short_desc>"
                       + matchResult.group(1)
                             .replace("&", "&amp;")
                             .replace("\"", "&quot;")
                             .replace("<", "&lt;")
                             .replace(">", "&gt;")
                       + "</short_desc>");