You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XML转Java对象遇&符号解析异常,求特殊符号值转字符串方案

解决XML转Java对象时未转义&符号的异常问题

问题本质

你遇到的jakarta.xml.bind.UnmarshalException是因为输入的XML不符合语法规范:XML中&是特殊字符,必须转义为&,而示例里Kondor#C&F#1435中的&未转义,被解析器误认为是实体引用的开头,因此报错实体"F"缺少分号结尾。


解决方案

方案一:预处理XML字符串,转义未合规的&

如果无法要求XML生成方修正输出,可先对输入字符串做预处理,仅替换未被转义的&:

// 正则匹配未转义的&(排除已经是合法实体的情况)
String cleanedXml = message.replaceAll("&(?!amp;|lt;|gt;|quot;|apos;)", "&");

// 使用处理后的字符串执行反序列化
JAXBContext context = JAXBContext.newInstance(className);
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader reader = new StringReader(cleanedXml);
Object unmarshalled = unmarshaller.unmarshal(reader);

该正则只会替换那些后面没有跟XML预定义实体后缀的&,不会破坏已正确转义的内容。

方案二:配置JAXB使用宽松解析器

通过自定义SAX解析器,关闭严格校验和实体解析:

JAXBContext context = JAXBContext.newInstance(className);
Unmarshaller unmarshaller = context.createUnmarshaller();

// 创建宽松模式的SAX解析器
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
spf.setFeature("http://xml.org/sax/features/validation", false);
XMLReader xmlReader = spf.newSAXParser().getXMLReader();
// 忽略实体解析请求
xmlReader.setEntityResolver((publicId, systemId) -> new InputSource(new StringReader("")));

// 包装为SAXSource进行反序列化
SAXSource source = new SAXSource(xmlReader, new InputSource(new StringReader(message)));
Object unmarshalled = unmarshaller.unmarshal(source);

方案三:XmlMapper(Jackson XML)的宽松配置

若使用XmlMapper,可通过开启宽松特性或自定义解析器解决:

XmlMapper xmlMapper = new XmlMapper();
// 允许未转义的特殊字符
xmlMapper.enable(FromXmlParser.Feature.ALLOW_UNQUOTED_CONTENT_CHARS);

// 或自定义XMLReader关闭实体校验
xmlMapper.getFactory().setXMLReaderFactory(() -> {
    try {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setFeature("http://xml.org/sax/features/validation", false);
        XMLReader reader = spf.newSAXParser().getXMLReader();
        reader.setEntityResolver((publicId, systemId) -> new InputSource(new StringReader("")));
        return reader;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
});

YourClass result = xmlMapper.readValue(message, YourClass.class);

注意事项

优先建议要求XML生成方输出合法的XML内容(对特殊字符进行转义),这是从根源解决问题的最优方案,上述方案仅作为无法修改输入时的临时替代。

内容的提问来源于stack exchange,提问作者Sergey Korotaev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:31:12