杰瑞科技汇

Java如何用XSD生成XML?

  1. 验证 - 你已经有一个 XML 文件,想用 XSD 来检查它是否符合规范。
  2. 生成 - 你有一个 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),我们的策略是:

  1. 根据 XSD 创建 Java 类:JAXB 提供了一个工具(xjc),可以直接从 XSD 文件生成一组 Java 类(POJOs),这些类完美地对应了 XSD 中的元素和类型。
  2. 编写 Java 代码:创建这些 Java 类的实例,并设置它们的属性值。
  3. 将 Java 对象编组为 XML:使用 JAXB 的 Marshaller 将 Java 对象转换为 XML 字符串或文件。

步骤 1:根据 XSD 生成 Java 类

JDK 中自带了 xjc 工具。

  1. 打开你的终端或命令行。

  2. 导航到你的项目目录,或者将 user.xsd 放在某个路径下。

  3. 运行以下命令:

    xjc user.xsd
  4. 执行成功后,你会看到生成了一个名为 generated 的新文件夹(或你指定的包名),里面包含了对应的 Java 文件:

    • ObjectFactory.java
    • User.java
    • User.Roles.java
    • package-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 类的实例并赋值。
使用 JAXBContextMarshaller 将对象转换为 XML。
用 XSD 验证 XML javax.xml.validation 使用 SchemaFactory 加载 XSD 文件创建 Schema
使用 Schema 创建 Validator
使用 Validatorvalidate() 方法验证 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>
分享:
扫描分享到社交APP
上一篇
下一篇