You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

添加docx4j与jaxb-runtime依赖后原有XML操作代码抛出NoClassDefFoundError异常的解决求助

添加docx4j与jaxb-runtime依赖后原有XML操作代码抛出NoClassDefFoundError异常的解决求助

问题背景

我之前有一段运行完全正常的XML重写代码,用来修改本地XML文件。但最近为了处理DOCX文档,在pom.xml里加了docx4j和jaxb-runtime这两个依赖,结果原来的XML操作代码在执行transformerFactory.newTransformer()这一行时,突然抛出了NoClassDefFoundError异常,提示找不到org/apache/xml/serializer/TreeWalker类。

原有正常运行的XML操作代码

private static void rewriteXmlDocument(Document document, File xmlFile) throws TransformerException,
FileNotFoundException {
  File temporaryFile = new File(xmlFile.getParent() + File.separator + "temporary.xml"); // 写入临时文件
  DOMSource source = new DOMSource(document);
  TransformerFactory transformerFactory = TransformerFactory.newInstance();

  Transformer transformer = transformerFactory.newTransformer();
  transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  transformer.setOutputProperty(OutputKeys.METHOD, "xml");
  transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

  if (temporaryFile.exists()) temporaryFile.delete(); // 清理旧临时文件
  StreamResult result = new StreamResult(new FileOutputStream(temporaryFile));
  transformer.transform(source, result);

  xmlFile.delete(); // 写入成功后删除原文件
  temporaryFile.renameTo(xmlFile); // 将临时文件重命名为原文件名
}

新增的Maven依赖

<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j</artifactId>
    <version>6.1.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.1</version>
</dependency>

抛出的异常信息

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/xml/serializer/TreeWalker
    at org.apache.xalan.processor.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:818)
    at AnanlyzeEmails/AnalyzeEmailsApplication.AnalyzeEmailsApp.rewriteXmlDocument(AnalyzeEmailsApp.java:170)

求问

有没有办法让我在保留docx4j和jaxb-runtime依赖的同时,让原来的XML操作代码恢复正常运行?


解决方案

这个问题的根源是docx4j的依赖传递干扰了原有XSLT转换器的类路径,导致Apache XML Serializer组件的类缺失。下面提供两种可行的解决思路:

方案1:显式补全缺失的XSLT相关依赖

直接在pom.xml中引入Xalan和对应的serializer依赖,补上找不到的TreeWalker类:

<dependency>
    <groupId>xalan</groupId>
    <artifactId>xalan</artifactId>
    <version>2.7.2</version>
</dependency>
<dependency>
    <groupId>xalan</groupId>
    <artifactId>serializer</artifactId>
    <version>2.7.2</version>
</dependency>

虽然Xalan依赖本身包含serializer,但由于依赖传递的优先级问题,单独显式引入serializer能更稳妥地解决类缺失问题。

方案2:切换使用JDK内置的TransformerFactory实现

如果不想额外引入依赖,也可以直接指定使用JDK自带的XSLT转换器实现,绕开第三方依赖的冲突:
修改XML操作代码中创建TransformerFactory的代码:

// 替换原来的 TransformerFactory.newInstance() 调用
TransformerFactory transformerFactory = TransformerFactory.newInstance(
    "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl",
    null
);

这样会直接使用JDK内置的XSLT实现,不受第三方依赖的影响,原有XML操作逻辑就能正常执行了。

补充说明

出现这个问题是因为docx4j可能引入了不同版本的Xalan,或者修改了类路径中XSLT相关组件的加载优先级,导致原本能正常找到的TreeWalker类现在无法加载。上面两种方案,一种是补全依赖,一种是换用无冲突的实现,你可以根据项目的依赖管理需求选择其中一种即可。

火山引擎 最新活动