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

dom4j从1.5.2升级至2.1.3后遇非法字符异常的解决问询

解决dom4j 2.1.3处理纯数字键JSON时的IllegalArgumentException问题

问题原因

dom4j 2.x版本开始严格遵循W3C XML规范,其中明确规定XML元素/属性名称不能以数字开头或为纯数字。而1.5.2版本的校验规则较为宽松,允许这类名称存在,所以升级后处理含纯数字键的JSON时触发IllegalArgumentException。

可行解决方案

1. 自定义名称校验器,放宽规则

dom4j支持自定义NameChecker来替换默认的严格校验逻辑,允许纯数字或数字开头的名称通过校验:

import org.dom4j.util.SimpleNameChecker;

public class LenientNameChecker extends SimpleNameChecker {
    @Override
    public boolean isValidName(String name) {
        // 允许纯数字或数字开头的名称,保留其他原有校验规则
        if (name != null && name.matches("^\\d+$|^\\d.*")) {
            return true;
        }
        return super.isValidName(name);
    }

    @Override
    public boolean isValidQName(String qualifiedName) {
        if (qualifiedName != null) {
            String localPart = qualifiedName.contains(":") 
                ? qualifiedName.split(":")[1] 
                : qualifiedName;
            if (localPart.matches("^\\d+$|^\\d.*")) {
                return true;
            }
        }
        return super.isValidQName(qualifiedName);
    }
}

在初始化dom4j时设置这个自定义校验器:

import org.dom4j.DocumentFactory;

// 全局设置自定义校验器
DocumentFactory factory = DocumentFactory.getInstance();
factory.setNameChecker(new LenientNameChecker());
// 后续所有dom4j操作使用这个factory实例

2. 预处理JSON,重命名纯数字键

在JSON数据进入dom4j处理前,自动给纯数字键添加前缀(比如num_),处理完成后如果需要再还原键名:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class JsonNumericKeyHandler {
    public static JsonNode renameNumericKeys(JsonNode node) {
        if (node.isObject()) {
            ObjectNode newObj = new ObjectMapper().createObjectNode();
            node.fieldNames().forEachRemaining(key -> {
                JsonNode value = node.get(key);
                // 仅对纯数字键添加前缀
                String newKey = key.matches("^\\d+$") ? "num_" + key : key;
                newObj.set(newKey, renameNumericKeys(value));
            });
            return newObj;
        } else if (node.isArray()) {
            node.elements().forEachRemaining(JsonNumericKeyHandler::renameNumericKeys);
        }
        return node;
    }
}

使用时先将JSON字符串转为JsonNode,调用该方法处理后再交给dom4j。

3. 启用dom4j非严格模式

通过系统属性关闭dom4j的严格校验,使其行为与1.5.2版本对齐:

  • 启动JVM时添加参数:-Ddom4j.strict=false
  • 或在代码中动态设置:
System.setProperty("dom4j.strict", "false");

注意:这是全局设置,可能会导致其他XML处理场景违反W3C规范,需谨慎使用。

方案选择建议

  • 若需要完全兼容旧版本行为,优先选择方案1或方案3;
  • 若业务允许临时修改键名,方案2更稳妥,不会影响XML规范符合性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:47:19