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

JAXB XML技术咨询:无需创建元素POJO类如何获取元素属性?

当然可行!在JAXB场景下,完全不用单独创建Child对应的POJO类,就能直接提取<child>元素的属性。下面给你两种实用的实现方式,按需选择:

方法一:使用JAXB标准API(无额外依赖)

这种方式基于JAXB自带的@XmlAnyElement注解配合自定义DomHandler,可以把目标子元素转换成一个普通的Java类来存储属性,不用给这个类加任何JAXB注解。

步骤1:定义属性存储类

先写一个普通的Java类,用来存<child>的属性,就是个简单的POJO,不需要JAXB相关注解:

public class ChildAttributes {
    private String name;
    private int age;

    public ChildAttributes() {}
    public ChildAttributes(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 生成getter和setter方法
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

步骤2:实现自定义DomHandler

这个Handler负责把XML里的<child>元素解析成上面的ChildAttributes对象:

import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.Element;

public class ChildAttributesHandler implements DomHandler<ChildAttributes, DOMResult> {

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

    @Override
    public ChildAttributes getElement(DOMResult result) {
        // 从DOM节点中提取属性
        Element childElement = (Element) result.getNode();
        String nameAttr = childElement.getAttribute("name");
        int ageAttr = Integer.parseInt(childElement.getAttribute("age"));
        return new ChildAttributes(nameAttr, ageAttr);
    }

    @Override
    public Source marshal(ChildAttributes attributes, ValidationEventHandler errorHandler) {
        // 如果只需要解析XML(不需要序列化),这里返回null即可
        return null;
    }
}

步骤3:编写Parent类

在Parent类里用@XmlAnyElement指定我们的自定义Handler,直接关联到ChildAttributes:

import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "parent")
public class Parent {
    private ChildAttributes childAttributes;

    @XmlAnyElement(ChildAttributesHandler.class)
    public ChildAttributes getChildAttributes() {
        return childAttributes;
    }

    public void setChildAttributes(ChildAttributes childAttributes) {
        this.childAttributes = childAttributes;
    }
}

测试代码

解析XML并获取属性:

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

public class JaxbTest {
    public static void main(String[] args) throws Exception {
        String xmlContent = "<parent> <child name=\"Child\" age=\"1\" /> </parent>";
        
        JAXBContext context = JAXBContext.newInstance(Parent.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Parent parent = (Parent) unmarshaller.unmarshal(new StringReader(xmlContent));
        
        System.out.println("Child名称:" + parent.getChildAttributes().getName());
        System.out.println("Child年龄:" + parent.getChildAttributes().getAge());
    }
}

如果你的项目可以引入第三方依赖,EclipseLink MOXy作为JAXB的一个增强实现,提供了@XmlPath注解,可以直接映射子元素的属性,连中间的属性存储类都省了。

步骤1:引入MOXy依赖

如果用Maven,在pom.xml里添加:

<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.moxy</artifactId>
    <version>4.0.2</version> <!-- 可以用最新稳定版 -->
</dependency>

步骤2:配置JAXB上下文工厂

在src/main/resources/META-INF目录下创建jaxb.properties文件,内容为:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

步骤3:编写Parent类

直接用@XmlPath注解映射<child>的属性:

import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name = "parent")
public class Parent {
    @XmlPath("child/@name")
    private String childName;
    
    @XmlPath("child/@age")
    private int childAge;

    // 生成getter和setter方法
    public String getChildName() { return childName; }
    public void setChildName(String childName) { this.childName = childName; }
    public int getChildAge() { return childAge; }
    public void setChildAge(int childAge) { this.childAge = childAge; }
}

测试代码

和方法一的测试逻辑类似,直接解析就能拿到属性:

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

public class MoxyTest {
    public static void main(String[] args) throws Exception {
        String xmlContent = "<parent> <child name=\"Child\" age=\"1\" /> </parent>";
        
        JAXBContext context = JAXBContext.newInstance(Parent.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Parent parent = (Parent) unmarshaller.unmarshal(new StringReader(xmlContent));
        
        System.out.println("Child名称:" + parent.getChildName());
        System.out.println("Child年龄:" + parent.getChildAge());
    }
}

两种方式都能满足你的需求:如果不想引入额外依赖,选方法一;如果追求代码简洁,选方法二。

内容的提问来源于stack exchange,提问作者Presto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:37:40