使用JAXB进行编组操作时如何移除多余的转义字符
问题根因
JAXB的Marshaller默认会对XML非法字符(&、<、>、"、')自动执行转义,你之前的代码中将自定义转义处理器的配置注释掉了,因此配置没有生效。
注意:生成未转义&的XML不符合W3C XML标准规范,后续标准XML解析器会直接报错无法解析该文件,仅在你明确不需要后续标准XML解析的场景下使用以下方案。
解决方案
方案1:Java 8及之前内置JAXB(Sun/GlassFish实现)适用
放开自定义转义逻辑的注释,配置直接输出原始字符不做转义即可,示例代码:
import com.sun.xml.bind.marshaller.CharacterEscapeHandler; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.File; import java.io.IOException; import java.io.Writer; private static void jaxbObjectToXML(Emp employee) { try { JAXBContext jaxbContext = JAXBContext.newInstance(Emp.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); // 核心配置:自定义转义处理器,跳过所有转义逻辑 jaxbMarshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() { @Override public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException { out.write(ch, start, length); } }); File file = new File("employee1.xml"); jaxbMarshaller.marshal(employee, file); System.out.println("done::"); } catch (JAXBException e) { e.printStackTrace(); } }
方案2:Java 9+外置Jakarta JAXB适用
Jakarta版本JAXB的转义处理器类路径和属性名有调整,修改配置如下:
import org.glassfish.jaxb.core.marshaller.CharacterEscapeHandler; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.Marshaller; // 其余逻辑不变,仅替换属性配置代码 jaxbMarshaller.setProperty(org.glassfish.jaxb.core.MarshallerProperties.CHARACTER_ESCAPE_HANDLER, (CharacterEscapeHandler) (ch, start, length, isAttVal, out) -> out.write(ch, start, length) );
合规场景替代方案
如果你需要既保留原始字符又符合XML规范,可以给对应字段添加@XmlCDATA注解,开启CDATA块处理,生成的内容会包裹在<![CDATA[]]>块中,既不会被转义也可以被标准XML解析器正常识别:
@XmlRootElement(name = "emp") public class Emp { @XmlCDATA private String address; private String name; // 省略getter、setter }
内容的提问来源于stack exchange,提问作者Naveen Kumar Mishra
相关产品推荐
相关产品推荐

