使用自定义转义某些符号 utf-8 和 utf-16 的解组器

问题描述

我有 XML 文件,其中一些符号由于混合使用 UTF-16 和 UTF-8 而被错误编码。

例如,? 符号被编码为 �� (��) 而不是 ? (📞)。

我想解组这个 XML 文件,但是当 Unmarshaller 遇到这些不正确的符号时它会失败。如果我只用 StringEscapeUtils#unescapeHtml4(或 StringEscapeUtils#unescapeXml)解码它们,一切正常。

但我不想将 XML 读取为字符串然后对其进行解码然后解组。

我如何在解组过程中做同样的事情(之前不要将 XML 文件读取为字符串)?

我创建了一个简单的测试来重现这个:

public class XmlReaderTest {

    private static final Pattern HTML_UNICODE_REGEX = Pattern.compile("&#[a-zA-Z0-9]+;&#[a-zA-Z0-9]+;");

    @Test
    public void test() throws Exception {
        final Unmarshaller unmarshaller = JAXBContext.newInstance(Value.class).createUnmarshaller();
        final XMLInputFactory factory = createXmlInputFactory();

        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><value><name>&#55357;&#56542; &amp; &#128222; O&#771;</name></value>";

        XMLEventReader xmlReader = factory.createXMLEventReader(new StringReader(decodeHtmlEntities(xml)));
        Value result = (Value)unmarshaller.unmarshal(xmlReader);
        assert result.name.equals("\uD83D\uDCDE & \uD83D\uDCDE Õ");

        XMLEventReader xmlReader2 = factory.createXMLEventReader(new StringReader(xml));
        Value result2 = (Value)unmarshaller.unmarshal(xmlReader2); // ! exception
        assert result2.name.equals("\uD83D\uDCDE & \uD83D\uDCDE Õ");
    }

    @XmlRootElement(name = "value")
    private static class Value {
        @XmlElement
        public String name;
    }

    private String decodeHtmlEntities(String readerString) {
        StringBuffer unescapedString = new StringBuffer();

        Matcher regexMatcher = HTML_UNICODE_REGEX.matcher(readerString);
        while (regexMatcher.find()) {
            regexMatcher.appendReplacement(unescapedString,StringEscapeUtils.unescapeHtml4(regexMatcher.group()));
        }
        regexMatcher.appendTail(unescapedString);

        return unescapedString.toString();
    }

    private XMLInputFactory createXmlInputFactory() {
        XMLInputFactory factory = XMLInputFactory.newFactory();
        factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,false);
        factory.setProperty(XMLInputFactory.SUPPORT_DTD,false);
        return factory;
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)