首页 > 解决方案 > 如何跳过 xml 标签内的文本验证?

问题描述

我正在以这种格式从 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; 错误信息: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.

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

找到下面使用的代码:

文件 file = new File("C:\test\file.xml");

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

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

标签: javaxmlparsingxsdxml-parsing

解决方案


如您所知,必须解析有效的 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 字符串中进行自我转义。

java 9修复:

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

或没有 apache common lang 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>");

推荐阅读