Java SOAP XML解析保留十六进制字符及Axis编码异常问题
解决方案
一、保留XML实体引用(不展开í为字符)
默认XML解析器会自动展开通用实体引用(如í)为对应字符,要保留原实体,需修改XMLHelper中的DocumentBuilderFactory配置,禁用实体展开特性:
修改XMLHelper的静态初始化块:
static { dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setNamespaceAware(true); dbFactory.setIgnoringElementContentWhitespace(true); // 添加以下配置阻止实体展开 try { // 禁用通用实体展开 dbFactory.setFeature("http://xml.org/sax/features/expand-general-entities", false); // 禁用参数实体展开(可选,根据需求) dbFactory.setFeature("http://xml.org/sax/features/expand-parameter-entities", false); } catch (ParserConfigurationException e) { // 根据实际情况处理异常,比如日志记录 e.printStackTrace(); } }
注意:部分XML解析器可能不支持上述特性,若无效,可尝试添加Apache Xerces的特定特性(需引入Xerces依赖):
dbFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
二、修复DOM转String的编码乱码问题
当前代码中new String(baos.toByteArray())会使用系统默认编码解析字节流,导致UTF-8字节被错误解析为Latin-1,出现Ã乱码。需明确指定编码:
修改DOM转String的代码段:
element = secSOAPReqDoc.getDocumentElement(); // Transformacion del elemento DOM a String source = new DOMSource(element); baos = new ByteArrayOutputStream(); streamResult = new StreamResult(baos); Transformer transformer = TransformerFactory.newInstance().newTransformer(); // 指定输出编码为UTF-8 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.transform(source, streamResult); // 使用UTF-8编码构造字符串 secSOAPReq = new String(baos.toByteArray(), StandardCharsets.UTF_8);
确保引入
java.nio.charset.StandardCharsets类(Java 7+可用),若使用低版本Java,可替换为"UTF-8"字符串:secSOAPReq = new String(baos.toByteArray(), "UTF-8");
三、验证签名与SOAP消息创建
编码问题修复后,重新生成的SOAP消息不会出现乱码,可避免Axis因参数修改抛出的异常。若仍有问题,需确认:
- XML解析后的
Document对象中实体引用是否被正确保留(可通过打印DOM节点类型验证,实体引用对应EntityReference节点) - WS-Security签名过程中是否修改了实体引用内容
内容的提问来源于stack exchange,提问作者C. M.
相关产品推荐
相关产品推荐

