Android集成docx4j遇FactoryConfigurationError:找不到MXParserFactory
问题描述
在Android项目中集成docx4j库操作.docx文件的复选框值时,读取Word文件抛出javax.xml.stream.FactoryConfigurationError错误,提示找不到Provider com.bea.xml.stream.MXParserFactory。
原项目配置与代码
Build.gradle 依赖配置
dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation files('libs\\awt-bastardised-17v8.jar') // implementation files('libs\\poishadow-all.jar') // implementation files('libs\\jaxb-core-4.0.1.jar') // implementation files('libs\\jaxb-api-2.3.0.jar') // implementation files('libs\\jaxb-impl-4.0.1.jar') // implementation files('libs\\javassist-3.29.2-GA.jar') // implementation files('libs\\jaxb-runtime-4.0.1.jar') // implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1' implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.0' implementation group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0' implementation group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.0' implementation group: 'javax.activation', name: 'activation', version: '1.1.1' // https://mvnrepository.com/artifact/org.docx4j/docx4j implementation group: 'org.docx4j', name: 'docx4j', version: '6.1.2' implementation group: 'com.google.guava', name: 'guava', version: '27.0.1-android' // implementation group: 'javax.xml.stream', name: 'stax-api', version: '1.0' // https://mvnrepository.com/artifact/stax/stax-api implementation group: 'stax', name: 'stax-api', version: '1.0.1' implementation group: 'org.docx4j', name: 'docx4j-MOXy-JAXBContext', version: '3.3.6' implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30' // implementation files('libs/docx4j-core-8.3.7.jar') // implementation files('libs/docx4j-JAXB-Internal-8.3.7.jar') // implementation files('libs/docx4j-openxml-objects-8.3.7.jar') // implementation files('libs/docx4j-openxml-objects-pml-8.3.7.jar') // implementation files('libs/docx4j-openxml-objects-sml-8.3.7.jar') // implementation files('libs/slf4j-api-1.7.2.jar') // implementation files('libs/javax.xml.bind.jar') // https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime // implementation("org.glassfish.jaxb:jaxb-runtime:4.0.0") // implementation 'javax.xml.bind:jaxb-api:2.2.12' // implementation files('libs/docx4j-core-11.4.8.jar') // implementation files('libs/docx4j-openxml-objects-pml-11.4.8.jar') // implementation files('libs/docx4j-openxml-objects-11.4.8.jar') // implementation files('libs/docx4j-openxml-objects-sml-11.4.8.jar') // implementation files('libs/jakarta.xml.bind-api-4.0.0.jar') // // https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-core // implementation("com.sun.xml.bind:jaxb-core:4.0.1") // https://mvnrepository.com/artifact/org.apache.commons/commons-compress // implementation("org.apache.commons:commons-compress:1.22") // https://mvnrepository.com/artifact/jakarta.xml.bind/jakarta.xml.bind-api // implementation("jakarta.xml.bind:jakarta.xml.bind-api:4.0.0") // https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl // implementation("com.sun.xml.bind:jaxb-impl:4.0.0") }
Kotlin 代码
var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { // There are no request codes val data: Intent? = result.data try { data?.data?.let { this.contentResolver?.openOutputStream(it)?.let { this.contentResolver.openInputStream(data.data!!)?.let { it2 -> val wordPackage: WordprocessingMLPackage = Docx4J.load(it2) val mainDocumentPart = wordPackage.mainDocumentPart val list = mainDocumentPart.getJAXBNodesViaXPath("//w14:checkbox", false) for (c in list) { val element: JAXBElement<CTSdtCheckbox> = c as JAXBElement<CTSdtCheckbox> val checkbox: CTSdtCheckbox = element.value val list2 = mainDocumentPart.getJAXBNodesViaXPath("../..//w:t", element, false) val chkSymbol: Text = (list2[0] as JAXBElement<Text>).value val checkedVal: org.docx4j.w14.CTOnOff? = checkbox.checked if (checkedVal?.getVal()?.compareTo("0") == 0) { checkedVal.setVal("1") chkSymbol.value = String(Character.toChars(0x2612)) } else { checkedVal?.setVal("0") chkSymbol.value = String(Character.toChars(0x2610)) } } } } } } catch (e: Exception) { Log.e("tag", "Exception: " + e.message) } } }
解决方案
1. 修正依赖配置
替换StAX相关依赖,添加具体的解析实现,同时调整docx4j的JAXB依赖版本:
dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation files('libs\\awt-bastardised-17v8.jar') // JAXB 相关依赖 implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1' implementation group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.1' implementation group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.1' implementation group: 'javax.activation', name: 'activation', version: '1.1.1' // docx4j 核心依赖 implementation group: 'org.docx4j', name: 'docx4j', version: '6.1.2' // 移除不匹配的MOXy依赖,改用docx4j自带的JAXB配置 // StAX 完整实现(API+解析器) implementation group: 'javax.xml.stream', name: 'stax-api', version: '1.0-2' implementation group: 'org.codehaus.woodstox', name: 'woodstox-core-asl', version: '4.4.1' implementation group: 'com.google.guava', name: 'guava', version: '27.0.1-android' implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30' }
2. 代码中指定StAX工厂实现
在加载docx文件前,添加系统属性配置,指定使用woodstox的StAX工厂,避免默认工厂查找失败:
var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { val data: Intent? = result.data try { // 配置StAX工厂 System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory") System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory") System.setProperty("javax.xml.stream.XMLEventFactory", "com.ctc.wstx.stax.WstxEventFactory") data?.data?.let { uri -> this.contentResolver.openInputStream(uri)?.let { inputStream -> val wordPackage: WordprocessingMLPackage = Docx4J.load(inputStream) val mainDocumentPart = wordPackage.mainDocumentPart val list = mainDocumentPart.getJAXBNodesViaXPath("//w14:checkbox", false) for (c in list) { val element: JAXBElement<CTSdtCheckbox> = c as JAXBElement<CTSdtCheckbox> val checkbox: CTSdtCheckbox = element.value val list2 = mainDocumentPart.getJAXBNodesViaXPath("../..//w:t", element, false) val chkSymbol: Text = (list2[0] as JAXBElement<Text>).value val checkedVal: org.docx4j.w14.CTOnOff? = checkbox.checked if (checkedVal?.getVal()?.compareTo("0") == 0) { checkedVal.setVal("1") chkSymbol.value = String(Character.toChars(0x2612)) } else { checkedVal?.setVal("0") chkSymbol.value = String(Character.toChars(0x2610)) } } // 补充修改后的文件保存逻辑 this.contentResolver.openOutputStream(uri)?.let { outputStream -> Docx4J.save(wordPackage, outputStream) } } } } catch (e: Exception) { Log.e("tag", "Exception: " + e.message, e) // 打印完整堆栈便于调试 } } }
额外说明
- 原代码缺少修改后的文件保存逻辑,已补充
Docx4J.save部分 - 添加完整的异常堆栈打印,方便排查后续问题
- 移除了版本不匹配的
docx4j-MOXy-JAXBContext依赖,避免JAXB上下文冲突
内容的提问来源于stack exchange,提问作者karan
相关产品推荐
相关产品推荐

