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

如何在不修改实体类注解前提下用JAXB正确序列化含CDATA的XML字符串

解决方案

方案1:直接解析XML片段为DOM节点挂载(匹配你给出的预期输出)

该方案无需使用CDATA,直接将你要插入的XML片段解析为DOM节点树后挂载到myTag节点下,序列化后内部XML会作为合法节点输出,无转义:

import java.io.ByteArrayInputStream
import java.io.StringWriter
import javax.xml.bind.JAXB
import javax.xml.parsers.DocumentBuilderFactory

fun main() {
    val documentBuilderFactory = DocumentBuilderFactory.newInstance()
    val documentBuilder = documentBuilderFactory.newDocumentBuilder()
    val document = documentBuilder.newDocument()

    val myElement = document.createElement("myTag")
    // 解析内部XML片段为DOM节点
    val innerXml = "<xml><a>text</a></xml>"
    val innerDoc = documentBuilder.parse(ByteArrayInputStream(innerXml.toByteArray()))
    // 将解析好的节点导入当前Document上下文并挂载
    val importedInnerNode = document.importNode(innerDoc.documentElement, true)
    myElement.appendChild(importedInnerNode)

    val myObject = MyObject().apply {
        element = myElement
    }
    val writer = StringWriter()
    JAXB.marshal(myObject, writer)
    println(writer.toString())
}

输出结果完全匹配你给出的预期格式。

方案2:保留CDATA格式不转义

如果你需要将内部XML作为纯文本存储在CDATA段中,不想让它被识别为父结构的子节点,可以自定义JAXB序列化器的转义逻辑,跳过CDATA内容的转义:

import java.io.StringWriter
import javax.xml.bind.JAXBContext
import javax.xml.bind.Marshaller
import javax.xml.parsers.DocumentBuilderFactory
import com.sun.xml.bind.marshaller.CharacterEscapeHandler

fun main() {
    val documentBuilderFactory = DocumentBuilderFactory.newInstance()
    val document = documentBuilderFactory.newDocumentBuilder().newDocument()

    val myElement = document.createElement("myTag")
    myElement.appendChild(document.createCDATASection("<xml><a>text</a>"))

    val myObject = MyObject().apply {
        element = myElement
    }

    // 自定义序列化配置
    val jaxbContext = JAXBContext.newInstance(MyObject::class.java)
    val marshaller = jaxbContext.createMarshaller()
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true)
    // 禁用转义逻辑(适配JDK默认的Sun JAXB实现)
    marshaller.setProperty("com.sun.xml.bind.characterEscapeHandler",
        CharacterEscapeHandler { chars, start, length, _, writer ->
            writer.write(chars, start, length)
        }
    )

    val writer = StringWriter()
    marshaller.marshal(myObject, writer)
    println(writer.toString())
}

该方案输出的CDATA段内容不会被转义,内部XML会完整保留在<![CDATA[...]]>包裹中。

内容的提问来源于stack exchange,提问作者J.Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:18:03