# JAXB 转换 XML

## 简介

JAXB（Java Architecture for XML Binding）是一个业界的标凖和数据绑定技术，通过使用 JAXB，可以将 XML 文档和 Java 对象之间进行映射，使得 XML 文档可以方便的转换成 Java 对象，也可以将 Java 对象转换成 XML 文档。

JAXB 为 XML Schema 和 Java 语言之间提供了一个简单的映射关系。它允许 Java 开发人员在 JavaBean 类中定义一个映射关系，然后使用 JAXB 映射工具将 JavaBean 对象转换成 XML 文件。可以基于注解或者 XML 配置文件来完成映射关系的定义。

```xml
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <scope>runtime</scope>
</dependency>
```

## JAXB 相关类与接口

### JAXBContext

`JAXBContext` 类提供了将 Java 对象序列化为 XML 和 XML 反序列化为 Java `对象的方法。JAXBContext` 类的实例是线程安全的，因此可以在多线程环境中共享。

`JAXBContext` 类的常用方法如下：

* `createMarshaller()`：创建一个 `Marshaller` 对象，用于将 Java 对象序列化为 XML。
* `createUnmarshaller()`：创建一个 `Unmarshaller` 对象，用于将 XML 反序列化为 Java 对象。
* `createValidator()`：创建一个 `Validator` 对象，用于验证 XML 内容。

### Marshaller

`Marshaller` 类用于将 Java 对象序列化为 XML `数据。Marshaller` 类的常用方法如下：

* `marshal(Object jaxbElement, Result result)`：将 Java 对象序列化为 XML 数据，并将结果输出到指定的 `Result` 对象中。
* `marshal(Object jaxbElement, OutputStream os)`：将 Java 对象序列化为 XML 数据，并将结果输出到指定的输出流中。
* `marshal(Object jaxbElement, Writer writer)`：将 Java 对象序列化为 XML 数据，并将结果输出到指定的字符输出流中。

### Unmarshaller

`Unmarshaller` 类用于将 XML 数据反序列化为 Java 对象。Unmarshaller 类的常用方法如下：

* `unmarshal(Source source)`：将 XML 数据反序列化为 Java 对象。
* `unmarshal(InputStream is)`：将 XML 数据反序列化为 Java 对象。
* `unmarshal(Reader reader)`：将 XML 数据反序列化为 Java 对象。

### Validator

`Validator` 类用于验证 XML 内容。Validator 类的常用方法如下：

* `validate(Source source)`：验证 XML 内容。
* `validate(InputStream is)`：验证 XML 内容。
* `validate(Reader reader)`：验证 XML 内容。

## JAXB 注解

JAXB 提供了一些注解，用于在 Java 类和 XML 文件之间建立映射关系。常用的 JAXB 注解如下：

<mark style="color:blue;">**`@XmlRootElement`**</mark><mark style="color:blue;">**：类级别注解，指定 Java 类映射到 XML 文件中的根元素。参数如下：**</mark>

* `name`：指定 XML 文件中的根元素的名称。默认使用类名作为根元素的名称。
* `namespace`：指定 XML 文件的命名空间。

<mark style="color:blue;">**`@XmlElement`**</mark><mark style="color:blue;">**：字段、方法、参数级别注解，该注解可以将被注解的（非静态）字段，或者**</mark><mark style="color:blue;">**&#x20;**</mark><mark style="color:blue;">**`get/set`**</mark><mark style="color:blue;">**&#x20;**</mark><mark style="color:blue;">**方法对应的字段映射到 XML 文件中的元素。参数如下：**</mark>

* `name`：指定 XML 文件中的元素的名称。默认使用小写属性名作为元素的名称。
* `namespace`：指定 XML 文件的命名空间。
* `required`：指定元素是否必须出现。默认值是 `false`。
* `nillable`：指定元素是否可以为 `null`。默认值是 `false`。
* `type`：指定该字段或属性的关联类型。

<mark style="color:blue;">**`@XmlType`**</mark><mark style="color:blue;">**：类级别注解，指定 Java 类映射到 XML Schema 中的类型。参数如下：**</mark>

* `name`：指定 XML Schema 中的类型的名称。默认使用类名作为类型的名称。
* `namespace`：指定 XML Schema 的命名空间。
* `propOrder`：指定 XML 元素的访问顺序。
* `factoryClass`：指定工厂类。
* `factoryMethod`：指定工厂方法。

<mark style="color:blue;">**`@XmlAttribute`**</mark><mark style="color:blue;">**：字段、方法级别的注解。该注解会将字段或者**</mark><mark style="color:blue;">**&#x20;**</mark><mark style="color:blue;">**`get/set`**</mark><mark style="color:blue;">**&#x20;**</mark><mark style="color:blue;">**方法对应的字段映射到 XML 文件中的属性。参数如下：**</mark>

* `name`：指定 XML 文件中的属性的名称。默认使用属性名作为属性的名称。
* `namespace`：指定 XML 文件的命名空间。
* `required`：指定属性是否必须出现。默认值是 `false`。
* `nillable`：指定属性是否可以为 `null`。默认值是 `false`。

<mark style="color:blue;">`@XmlAccessorType`</mark><mark style="color:blue;">：指定映射到 XML 元素的访问类型。默认值是</mark> <mark style="color:blue;"></mark><mark style="color:blue;">`XmlAccessType.PUBLIC_MEMBER`</mark><mark style="color:blue;">。参数如下：</mark>

* `XmlAccessType.FIELD`：将 Java 类的所有字段映射到 XML 元素。
* `XmlAccessType.PROPERTY`：将 Java 类的 `get/set` 方法映射到 XML 元素。
* `XmlAccessType.PUBLIC_MEMBER`：将 Java 类的所有公共字段和 `get/set` 方法映射到 XML 元素。
* `XmlAccessType.NONE`：不映射任何字段或方法。

`@XmlAccessorOrder`：指定映射到 XML 元素的访问顺序。

`@XmlEnum`：枚举类级别注解，指定枚举类映射到 XML Schema 中的类型。

<mark style="color:blue;">`@XmlSchema`</mark><mark style="color:blue;">：包级别注解，指定包中的所有类映射到 XML Schema 中的命名空间。</mark>

{% code title="package-info.java" overflow="wrap" %}

```java
@XmlSchema(namespace = "http://www.example.com/employee", elementFormDefault = XmlNsForm.QUALIFIED)
package com.example.demo.entity;

import jakarta.xml.bind.annotation.XmlNsForm;
import jakarta.xml.bind.annotation.XmlSchema;
```

{% endcode %}

## JAXB 示例

```java
@Data
@XmlRootElement(name = "book")
@XmlAccessorType(XmlAccessType.FIELD)
public class Book {
    private String title;
    private String author;
    private double price;
}
```

```xml
<?xml version="1.0" encoding="UTF-8"?>
<book>
    <title>Java 编程思想</title>
    <author>埃克尔</author>
    <price>108.0</price>
</book>
```

```java
// 创建 JAXBContext 对象
JAXBContext context = JAXBContext.newInstance(Book.class);
// 创建 Marshaller 对象
Marshaller marshaller = context.createMarshaller();
// 创建 Book 对象
Book book = new Book();
book.setTitle("Java 编程思想");
book.setAuthor("埃克尔");
book.setPrice(108.0);
// 将 Java 对象序列化为 XML
StringWriter writer = new StringWriter();
marshaller.marshal(book, writer);
System.out.println(writer.toString());
// 创建 Unmarshaller 对象
Unmarshaller unmarshaller = context.createUnmarshaller();
// 将 XML 反序列化为 Java 对象
Book book2 = (Book) unmarshaller.unmarshal(new StringReader(writer.toString()));
System.out.println(book2.getTitle());
System.out.println(book2.getAuthor());
System.out.println(book2.getPrice());
```
