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扩展(更简洁)
如果你的项目可以引入第三方依赖,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
相关产品推荐
相关产品推荐

