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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:15:32