JAXB(Java Architecture for XML Binding)是Java API的一部分,它提供了一种将Java类映射到XML结构的方式,也可以将XML结构转换为Java类的实例。它是一种简化Java与XML交互的方式,可以通过注释或外部XML映射文件将Java类与XML元素映射起来。
JAXB包含了两个主要的类:Unmarshaller
和Marshaller
。Unmarshaller
可以将XML文档转换为Java对象,而Marshaller
则可以将Java对象转换为XML文档。而XJC是JAXB的一个辅助工具,用于根据XML Schema生成Java类。它会自动解析XML Schema中定义的元素和属性,并将它们转换为Java类和字段。使用XJC可以减少手动编写Java类的工作量,同时保证生成的Java类与XML Schema定义的数据模型一致。
JAXB可以与其他XML处理技术,如DOM、SAX和StAX一起使用。使用JAXB可以轻松地实现Java与XML的转换,使Java开发人员更加专注于业务逻辑的实现。
xjc 是 JAXB 工具集中的一个命令行工具,可以根据 XML Schema 文件自动生成 Java 类。jdk 11以下都自带xjc, 位置: %JAVA_HOME%\bin\xjc.exe;
下面是使用 xjc 工具生成 Java 类的步骤:
示例一和示例二的区别
xsd的定义结构不同,示例二采用类似匿名类的形式进行编写。
如果生成的ObjectFactory.java中包含@XmlElementDecl , 则使用ObjectFactory.java进行解析,如示例一;不包含则使用对应的类来解析,如示例二
示例一:需要手动给PersonType.java中增加@XmlRootElement,才能将java对象解析成xml
使用任何文本编辑器编写 XML Schema 文件。下面是一个示例 XML Schema 文件:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:int"/>
<xs:element name="address" type="addressType"/>
xs:sequence>
xs:complexType>
<xs:complexType name="addressType">
<xs:sequence>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
xs:sequence>
xs:complexType>
xs:schema>
对应的person.xml文件是:
<person>
<name>zhangsanname>
<age>13age>
<address>
<city>chinacity>
<country>beijingcountry>
address>
person>
# -d 参数指定生成的 Java 类的输出目录,-p 参数指定生成的 Java 类的包名
# 该命令会自动生成一个名为 PersonType.java 的 Java 类和名为addressType.java的Java类,以及一个名为 ObjectFactory.java 的工厂类,用于创建 JAXBContext 对象
# xjc schema.xsd -d src -p com.example.person
xjc resource/xsd/person.xsd -p test_person.gensrc
@XmlAccessorType 注解用于指定 JAXB 应该使用属性访问器而非字段访问器,
@XmlType 注解用于指定类的名称和属性顺序
@XmlRootElement 注解用于指定类在 XML 文档中的根元素名称
// Persion.java
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 http://java.sun.com/xml/jaxb
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2023.03.29 时间 11:42:15 AM CST
//
package test_person.gensrc;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "personType", propOrder = {
"name",
"age",
"address"
})
public class PersonType {
@XmlElement(required = true)
protected String name;
protected int age;
@XmlElement(required = true)
protected AddressType address;
// 此处省略 get 和 set方法
}
// AddressType.java
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 http://java.sun.com/xml/jaxb
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2023.03.29 时间 11:42:15 AM CST
//
package test_person.gensrc;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "addressType", propOrder = {
"city",
"country"
})
public class AddressType {
@XmlElement(required = true)
protected String city;
@XmlElement(required = true)
protected String country;
// get 和 set方法省略
}
// ObjeceMapper.java --用于创建 JAXBContext 对象
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 http://java.sun.com/xml/jaxb
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2023.03.29 时间 11:42:15 AM CST
//
package test_person.gensrc;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
private final static QName _Person_QNAME = new QName("", "person");
public ObjectFactory() {
}
public PersonType createPersonType() {
return new PersonType();
}
public AddressType createAddressType() {
return new AddressType();
}
@XmlElementDecl(namespace = "", name = "person")
public JAXBElement<PersonType> createPerson(PersonType value) {
return new JAXBElement<PersonType>(_Person_QNAME, PersonType.class, null, value);
}
}
package TestXjc.com.example.persion;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import java.io.File;
public class Test {
public static void main(String[] args) throws Exception {
// 通过ObjectFactory来解析xml文件
JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
File xmlFile = new File("/home/cienet/IdeaProjects/myTest/src/TestXjc/person.xml");
JAXBElement<?> jaxbElement = (JAXBElement<?>) unmarshaller.unmarshal(xmlFile);
PersonType personType = (PersonType) jaxbElement.getValue();
//AddressType addressType = (AddressType) jaxbElement.getValue(); 会发生报错
System.out.println(personType.age);
// 将java对象转换为xml文件
// 需要手动给PersonType.java中增加@XmlRootElement,才能将java对象解析成xml
PersonType personType = new PersonType();
personType.setAge(88);
JAXBContext jaxbContext = JAXBContext.newInstance(PersonType.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化输出
try (FileOutputStream fileStream = new FileOutputStream("C:\\Users\\mats\\IdeaProjects\\xmlParse\\src\\resource\\xml\\person_new.xml")) {
marshaller.marshal(personType, fileStream);
}
}
}
使用任何文本编辑器编写 XML Schema 文件。下面是一个示例 XML Schema 文件:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ServerConfig">
<xs:complexType>
<xs:all>
<xs:element name="ServerInfo">
<xs:complexType>
<xs:attribute name="serverId" type="xs:string"/>
<xs:attribute name="protocol" type="xs:string"/>
<xs:attribute name="port" type="xs:int"/>
xs:complexType>
xs:element>
<xs:element name="BadiduInfo">
<xs:complexType>
<xs:attribute name="url" type="xs:string" />
xs:complexType>
xs:element>
xs:all>
xs:complexType>
xs:element>
xs:schema>
对应的server_config.xml文件是:
<ServerConfig>
<ServerInfo serverId="1" protocol="http" port="80" />
<BadiduInfo url="https://www.baidu.com" />
ServerConfig>
# -d 参数指定生成的 Java 类的输出目录,-p 参数指定生成的 Java 类的包名
# 该命令会自动生成一个名为 PersonType.java 的 Java 类和名为addressType.java的Java类,以及一个名为 ObjectFactory.java 的工厂类,用于创建 JAXBContext 对象
# xjc schema.xsd -d src -p com.example.person
xjc resource/xsd/server_config.xsd -p test_serverConfig.gnsrc
@XmlAccessorType 注解用于指定 JAXB 应该使用属性访问器而非字段访问器,
@XmlType 注解用于指定类的名称和属性顺序
@XmlRootElement 注解用于指定类在 XML 文档中的根元素名称
// ServerConfig.java
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 http://java.sun.com/xml/jaxb
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2023.03.29 时间 11:42:15 AM CST
//
package test_serverConfig.gnsrc;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
})
@XmlRootElement(name = "ServerConfig")
public class ServerConfig {
@XmlElement(name = "ServerInfo", required = true)
protected ServerConfig.ServerInfo serverInfo;
@XmlElement(name = "BadiduInfo", required = true)
protected ServerConfig.BadiduInfo badiduInfo;
// 此处省略get和set方法
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
public static class BadiduInfo {
@XmlAttribute(name = "url")
protected String url;
// 此处省略get和set方法
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
public static class ServerInfo {
@XmlAttribute(name = "serverId")
protected String serverId;
@XmlAttribute(name = "protocol")
protected String protocol;
@XmlAttribute(name = "port")
protected Integer port;
// 此处省略get和set方法
}
}
// ObjeceMapper.java
// 此文件是由 JavaTM Architecture for XML Binding (JAXB) 引用实现 v2.2.8-b130911.1802 生成的
// 请访问 http://java.sun.com/xml/jaxb
// 在重新编译源模式时, 对此文件的所有修改都将丢失。
// 生成时间: 2023.03.29 时间 11:42:15 AM CST
//
package test_serverConfig.gensrc;
import javax.xml.bind.annotation.XmlRegistry;
@XmlRegistry
public class ObjectFactory {
public ObjectFactory() {
}
public ServerConfig createServerConfig() {
return new ServerConfig();
}
public ServerConfig.ServerInfo createServerConfigServerInfo() {
return new ServerConfig.ServerInfo();
}
public ServerConfig.BadiduInfo createServerConfigBadiduInfo() {
return new ServerConfig.BadiduInfo();
}
}
package test_serverConfig;
import test_serverConfig.gensrc.ServerConfig;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.File;
public class Test {
public static void main(String[] args) throws Exception {
// xml转换为java
// 通过ServerConfig来解析xml文件
JAXBContext jaxbContext = JAXBContext.newInstance(ServerConfig.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
File xmlFile = new File("C:\\Users\\mats\\IdeaProjects\\xmlParse\\src\\resource\\xml\\server_config.xml");
ServerConfig serverConfig= (ServerConfig) unmarshaller.unmarshal(xmlFile);
System.out.println(serverConfig.getServerInfo().getServerId());
// java转换为xml
ServerConfig.BadiduInfo badiduInfo=new ServerConfig.BadiduInfo();
badiduInfo.setUrl("www.baidu.com");
serverConfig.setBadiduInfo(badiduInfo);
jaxbContext = JAXBContext.newInstance(ServerConfig.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化输出
try (FileOutputStream fileStream = new FileOutputStream("C:\\Users\\mats\\IdeaProjects\\xmlParse\\src\\resource\\xml\\server_config_new.xml")) {
marshaller.marshal(serverConfig, fileStream);
}
}
}