- 验证 - 你已经有一个 XML 文件,想用 XSD 来检查它是否符合规范。
- 生成 - 你有一个 XSD 文件,想用它作为模板来自动创建符合规范的 XML 文件。
根据你的问题“生成 xml”,我将重点讲解 场景二,并提供 场景一 的代码作为补充。
核心思想
从 XSD 生成 XML 的核心思想是:XSD 本身是一个结构化的“蓝图”或“模板”,Java 的 API(主要是 javax.xml 包)可以解析这个蓝图,然后我们通过编程的方式,按照蓝图的结构一步步地填充数据,最终构建出 XML 文档。
这个过程不是“一键生成”的,它需要你编写代码来创建 XML 的各个元素和属性,并确保它们符合 XSD 的定义(<name> 元素必须出现,<age> 元素必须是数字类型等)。
我们将使用 Java 内置的 JAXB (Java Architecture for XML Binding) API 来完成这个任务,因为它能极大地简化 XML 的生成和解析过程。
准备工作:定义一个 XSD 文件
我们创建一个示例 XSD 文件,它将作为我们生成 XML 的模板,假设我们要生成一个描述“用户”信息的 XML。
user.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="user">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:positiveInteger"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="email" type="xs:string"/>
<xs:element name="age" type="xs:integer" minOccurs="0"/>
<xs:element name="roles">
<xs:complexType>
<xs:sequence>
<xs:element name="role" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="isActive" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
这个 XSD 定义了一个 user 元素,它包含 id, name, email, age (可选), roles (一个可包含多个 role 的列表) 等子元素,以及一个必需的 isActive 属性。
使用 XSD 生成 XML (重点)
我们将使用 JAXB 来实现,JAXB 可以将 Java 对象映射到 XML(称为编组/Marshalling),反之亦然(称为解组/Unmarshalling),我们的策略是:
- 根据 XSD 创建 Java 类:JAXB 提供了一个工具(
xjc),可以直接从 XSD 文件生成一组 Java 类(POJOs),这些类完美地对应了 XSD 中的元素和类型。 - 编写 Java 代码:创建这些 Java 类的实例,并设置它们的属性值。
- 将 Java 对象编组为 XML:使用 JAXB 的
Marshaller将 Java 对象转换为 XML 字符串或文件。
步骤 1:根据 XSD 生成 Java 类
JDK 中自带了 xjc 工具。
-
打开你的终端或命令行。
-
导航到你的项目目录,或者将
user.xsd放在某个路径下。 -
运行以下命令:
xjc user.xsd
-
执行成功后,你会看到生成了一个名为
generated的新文件夹(或你指定的包名),里面包含了对应的 Java 文件:ObjectFactory.javaUser.javaUser.Roles.javapackage-info.java
这些类就是我们将要用来构建 XML 的“积木”。
步骤 2:编写 Java 代码生成 XML
我们创建一个新的 Java 类来执行生成逻辑。
XmlGenerator.java
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.annotation.*;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
// 注意:从 JDK 9+ 开始,JAXB 包从 javax.xml.bind 移到了 jakarta.xml.bind
// 如果你使用的是 JDK 8,请将 jakarta 改为 javax
public class XmlGenerator {
public static void main(String[] args) {
try {
// 1. 创建 JAXBContext 实例,传入我们生成的根类 User.class
JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
// 2. 创建 Marshaller 实例,用于将 Java 对象转换为 XML
Marshaller marshaller = jaxbContext.createMarshaller();
// 3. 设置输出格式,使其格式化、美化输出
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// 设置字符编码
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
// 4. 创建并填充 Java 对象(这些对象是 xjc 工具生成的)
User user = new User();
user.setId(101L);
user.setName("张三");
user.setEmail("zhangsan@example.com");
user.setAge(30);
// 处理 isActive 属性
user.setIsActive(true);
// 处理 roles 列表
List<String> roles = new ArrayList<>();
roles.add("管理员");
roles.add("开发者");
user.getRoles().setRole(roles);
// 5. 将 Java 对象转换为 XML 字符串
StringWriter writer = new StringWriter();
marshaller.marshal(user, writer);
// 6. 打印生成的 XML
String xmlOutput = writer.toString();
System.out.println(xmlOutput);
// 如果你希望将 XML 保存到文件中
// marshaller.marshal(user, new File("user.xml"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
// --- 以下是 xjc 工具从 user.xsd 生成的类 ---
// 为了让这个文件能独立编译,我把它们也放在这里了。
// 在实际项目中,你只需要将 xjc 生成的类放到你的源代码目录即可。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"id",
"name",
"email",
"age",
"roles"
})
@XmlRootElement(name = "user")
class User {
@XmlElement(required = true)
protected long id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true)
protected String email;
protected Integer age;
protected User.Roles roles;
@XmlAttribute(name = "isActive", required = true)
protected boolean isActive;
// Getters and Setters...
public long getId() { return id; }
public void setId(long value) { this.id = value; }
public String getName() { return name; }
public void setName(String value) { this.name = value; }
public String getEmail() { return email; }
public void setEmail(String value) { this.email = value; }
public Integer getAge() { return age; }
public void setAge(Integer value) { this.age = value; }
public User.Roles getRoles() {
if (roles == null) {
roles = new User.Roles();
}
return roles;
}
public boolean isIsActive() { return isActive; }
public void setIsActive(boolean value) { this.isActive = value; }
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"role"
})
static class Roles {
@XmlElement(required = true)
protected List<String> role;
public List<String> getRole() {
if (role == null) {
role = new ArrayList<String>();
}
return this.role;
}
}
}
运行结果
运行 XmlGenerator.java,你将得到以下符合 user.xsd 规范的 XML 输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user isActive="true">
<id>101</id>
<name>张三</name>
<email>zhangsan@example.com</email>
<age>30</age>
<roles>
<role>管理员</role>
<role>开发者</role>
</roles>
</user>
使用 XSD 验证 XML (补充)
虽然你的问题是“生成”,但了解如何验证也非常有用。
XmlValidator.java
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.StringReader;
public class XmlValidator {
public static void main(String[] args) {
// 要验证的 XML 字符串
String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<user isActive=\"true\">\n" +
" <id>101</id>\n" +
" <name>张三</name>\n" +
" <email>zhangsan@example.com</email>\n" +
" <age>30</age>\n" +
" <roles>\n" +
" <role>管理员</role>\n" +
" <role>开发者</role>\n" +
" </roles>\n" +
"</user>";
// XSD 文件路径
String xsdPath = "user.xsd";
try {
// 1. 创建 SchemaFactory
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// 2. 创建 Schema,传入 XSD 文件
Schema schema = factory.newSchema(new File(xsdPath));
// 3. 创建 Validator
Validator validator = schema.newValidator();
// 4. 执行验证
System.out.println("开始验证 XML...");
validator.validate(new StreamSource(new StringReader(xmlString)));
System.out.println("XML 文件验证成功!它符合 XSD 规范。");
} catch (SAXException e) {
// SAXException 表示验证失败
System.err.println("验证失败: " + e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意:javax.xml.validation API 是 Java 标准库的一部分,无需额外依赖。
总结与关键点
| 任务 | 核心技术 | 步骤 |
|---|---|---|
| 从 XSD 生成 XML | JAXB (编组/Marshalling) | 使用 xjc 工具从 XSD 生成 Java 类。创建这些 Java 类的实例并赋值。 使用 JAXBContext 和 Marshaller 将对象转换为 XML。 |
| 用 XSD 验证 XML | javax.xml.validation |
使用 SchemaFactory 加载 XSD 文件创建 Schema。使用 Schema 创建 Validator。使用 Validator 的 validate() 方法验证 XML。 |
JAXB 版本说明:
- JDK 8 及更早版本: 使用
javax.xml.bind包,这是标准做法。 - JDK 9+:
javax.xml.bind被移到了jakarta.xml.bind,如果你在较新的 JDK 上运行,并且遇到ClassNotFoundException,请将代码中的javax替换为jakarta,如果你使用 Maven/Gradle,需要添加相应的依赖。
Maven 依赖 (JDK 9+):
<dependencies>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>4.0.3</version>
</dependency>
</dependencies> 