Dom4j解析XML丢失文本中换行符的问题解决

问题描述

程序员还是看代码好了:

public static void main(String[] args) throws DocumentException {
    String text = "";
    Document document = DocumentHelper.parseText(text);
    System.out.println(document.valueOf("//root/@value"));
}

虽然我的内容里面有换行符,但是打印出的结果是123 321

排查过程

最开始怀疑是document.valueOf()的问题,然而看document的结构发现里面的属性已经是错误的了。那问题出在DocumentHelper.parseText()这里。

然后就是常规跟代码,看看到底是哪里把我们的代码处理成空格的。

最后发现了com.sun.org.apache.xerces.internal.impl.XMLScanner#scanAttributeValue,涉及到我们问题的代码片段如下:

else if (c == '\n' || c == '\r') {
    fEntityScanner.scanChar();
    stringBuffer.append(' ');
    if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
        fStringBuffer2.append('\n');
    }
}

关键行是stringBuffer.append(' ')这里解析到有换行符后,他没有原封不动把换行符加入到结果中,而是加入了空格。

这里还有一个信息就是entityDepth == fEntityDepth && fNeedNonNormalizedValue条件,我们可以猜想我们可能是可以通过设置参数来影响解析XML的过程的,使它能原封把换行符放入结果,因为时间关系这里没有继续的往下查代码。

解决过程

以前想要修改jar里面的代码,我们都是在我们的源码中创建与原类相同的包路径和java文件。这样我们可以编译构建的过程中用我们的代码来覆盖原有jar包中的class。

但是这次照做之后发现没有替换成功。原因在于,这次想要覆盖的是java的代码。我们可以想到java的类肯定会优先加载,或者使用自己的classloader进行加载,这样就把我们的意图给破坏掉了。

但是java也不是没有给我们留后门。这时候就有个JVM的配置参数

-Djava.endorsed.dirs=I:\xml\

配置好了这个,JVM就会去配置的目录中找jar并加载。

我们再需要做的就是把编译后的XMLScanner.class打成jar包。

使用命令

jar -cvf xml.jar *

并放到上面配置的目录下就可以啦。

后续

  1. 研究JVM的加载原理及顺序
  2. 研究除了配置endorsed,考虑使用javaagent的方式进行增强
  3. 研究是不是可以通过配置来解决此问题

你可能感兴趣的:(Dom4j解析XML丢失文本中换行符的问题解决)