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

如何使用JAXB将XML文件的子部分解析为标签不含命名空间的原始XML字符串

如何使用JAXB将XML文件的子部分解析为标签不含命名空间的原始XML字符串

嘿,刚好我之前处理过一模一样的需求——用JAXB映射大部分XML节点到Java类,只把指定节点下的内容原封不动(带标签)转成字符串,还得去掉命名空间痕迹。下面给你详细说具体怎么实现:

第一步:定义Java实体类结构

首先我们要把XML里的非ItemDescription部分映射成常规的Java类,ItemDescription则单独做包装类,用来存kind属性和原始XML字符串:

1. 主实体类 Item

这个类对应XML根节点,映射ID和所有ItemDescription节点:

import javax.xml.bind.annotation.*;
import java.util.List;

@XmlRootElement(name = "Item", namespace = "http://www.example.com/item")
@XmlAccessorType(XmlAccessType.FIELD)
public class Item {
    private String ID;

    @XmlElement(name = "ItemDescription")
    private List<ItemDescriptionContent> itemDescriptions;

    // 别忘了生成getter和setter方法
}

2. ItemDescription包装类 ItemDescriptionContent

这里是关键,用@XmlAnyElement指定自定义的DomHandler,让JAXB把节点内容交给我们自己处理:

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class ItemDescriptionContent {
    @XmlAttribute
    private String kind;

    // 用自定义DomHandler处理子节点,转成原始XML字符串
    @XmlAnyElement(MyDomHandler.class)
    private String rawXmlContent;

    // getter和setter方法
}

第二步:实现自定义DomHandler处理节点转字符串(去命名空间)

核心逻辑就在这个DomHandler里,它负责把XML节点转换成字符串,同时移除所有命名空间相关的内容:

import org.w3c.dom.*;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;

public class MyDomHandler implements DomHandler<String, StreamResult> {

    private StringWriter xmlWriter = new StringWriter();

    @Override
    public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
        return new StreamResult(xmlWriter);
    }

    @Override
    public String getElement(StreamResult rt) {
        // 先拿到带命名空间的原始XML字符串
        String rawXml = rt.getWriter().toString();
        // 移除所有命名空间声明(比如xmlns="xxx")
        rawXml = rawXml.replaceAll(" xmlns(:\\w+)?=\"[^\"]*\"", "");
        // 移除标签里的命名空间前缀(比如<ns0:p>变成<p>)
        rawXml = rawXml.replaceAll("<(/)?\\w+:", "<$1");
        return rawXml.trim();
    }

    @Override
    public Source marshal(String n, ValidationEventHandler errorHandler) {
        // 如果需要把字符串写回XML的话再完善这个方法,解析阶段可以先这么简单实现
        try {
            DOMSource source = new DOMSource();
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            transformer.transform(new StreamResult(new StringReader(n)), new DOMResult(source.getNode()));
            return source;
        } catch (TransformerException e) {
            throw new RuntimeException("Failed to marshal raw XML", e);
        }
    }
}

第三步:测试解析代码

最后写个测试类验证一下,把你的item.xml文件解析成Java对象,然后打印出ItemDescription的原始XML内容:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.File;

public class JaxbParserTest {
    public static void main(String[] args) throws Exception {
        JAXBContext context = JAXBContext.newInstance(Item.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Item item = (Item) unmarshaller.unmarshal(new File("item.xml"));

        // 遍历输出结果
        for (ItemDescriptionContent desc : item.getItemDescriptions()) {
            System.out.println("Kind: " + desc.getKind());
            System.out.println("Raw XML Content:\n" + desc.getRawXmlContent());
            System.out.println("------------------------");
        }
    }
}

效果说明

运行测试代码后,你会得到这样的输出:

Kind: long
Raw XML Content:
<p>
    <u>This is a description</u>
</p>
<br/>
<p>End Of description</p>
------------------------
Kind: short
Raw XML Content:
<p>
    <u>This is a description</u>
</p>
------------------------

完全符合你的需求:其他节点正常映射Java类,ItemDescription下的所有内容(带标签)转成字符串,而且没有任何命名空间痕迹。

备注:内容来源于stack exchange,提问作者bloub

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 11:18:15