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
相关产品推荐
相关产品推荐

