乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • XML 基础语法

    • XML 概述
    • XML 文档结构
    • XML 元素
    • XML 属性
    • XML 语法规则
    • XML 命名空间
    • XML 注释与处理指令
  • DTD 与文档验证

    • DTD 概述
    • DTD 元素声明
    • DTD 属性声明
    • DTD 实体声明
    • DTD 元素与属性对比
    • DTD 完整示例
  • XML Schema 定义

    • XML Schema 概述
    • XSD 简单类型
    • XSD 复杂类型
    • XSD 命名空间与引用
  • XPath 节点定位

    • XPath 概述
    • XPath 路径表达式
    • XPath 谓词与函数
  • XSLT 转换

    • XSLT 概述
    • XSLT 模板与匹配
    • XSLT 控制结构
    • XSLT 输出控制
  • XML 解析技术

    • XML 解析概述
    • DOM 解析
    • SAX 解析
    • StAX 解析
    • XML 与 Java — JAXP
  • XML 在 Java 中的应用

    • Spring XML 配置
    • MyBatis XML 映射
    • pom.xml 与 Maven
    • web.xml 配置详解
  • 现代数据格式对比

    • XML 与 JSON 对比
    • XML 与 YAML 对比
  • XML 显示与浏览器集成

    • XML 在浏览器中的显示
    • XMLHttpRequest 与 AJAX
    • 服务器端 XML 处理
  • XML 进阶查询与链接

    • XQuery 查询语言
    • XLink 超链接
    • XML 验证工具使用
  • XML Web 服务(选读)

    • XML Web 服务概述
    • SOAP 协议详解
    • WSDL 服务描述
    • RSS 内容聚合
    • RDF 资源描述框架

XML 与 Java — JAXP

本章定位 :掌握 JAXP(Java API for XML Processing)的架构——整合 DOM/SAX/StAX/XSLT/Schema 的五合一门面,理解 Factory 模式和可插拔实现机制。

定义与作用

JAXP (Java API for XML Processing)不是一种新的解析技术,而是 Java 标准库中 整合所有 XML 处理 API 的统一门面 。

JAXP 提供了:

  • DOM 解析 :DocumentBuilderFactory → DocumentBuilder
  • SAX 解析 :SAXParserFactory → SAXParser
  • StAX 解析 :XMLInputFactory / XMLOutputFactory
  • XSLT 转换 :TransformerFactory → Transformer
  • Schema 验证 :SchemaFactory → Schema → Validator

JAXP 的核心设计是 可插拔——通过 Factory 模式,你写的代码不依赖于具体的解析器实现(如 Xerces),可以在运行时切换。

核心原理:JAXP 架构全景

图解释 :JAXP 是一层抽象门面。应用只依赖 javax.xml.* 接口,具体实现(Xerces/Woodstox/Saxon)通过 ServiceLoader 机制在运行时加载。这种设计让你可以切换实现而不改代码。

语法/结构要点

五大 Factory 对比

Factory产物用途
DocumentBuilderFactoryDocumentBuilderDOM 解析(parse → Document)
SAXParserFactorySAXParserSAX 解析(parse → 事件回调)
XMLInputFactoryXMLStreamReader / XMLEventReaderStAX 读取
TransformerFactoryTransformerXSLT 转换
SchemaFactorySchema → ValidatorXSD 验证

Schema 验证流程

// 1. 创建 SchemaFactory
SchemaFactory sf = SchemaFactory.newInstance(
    XMLConstants.W3C_XML_SCHEMA_NS_URI);

// 2. 编译 XSD 为 Schema 对象
Schema schema = sf.newSchema(new File("bookstore.xsd"));

// 3. 创建 Validator
Validator validator = schema.newValidator();

// 4. 设置错误处理器
validator.setErrorHandler(new DefaultHandler() {
    public void error(SAXParseException e) {
        System.out.println("验证错误: " + e.getMessage());
    }
});

// 5. 验证 XML
validator.validate(new StreamSource(new File("bookstore.xml")));

完整示例:白歌整合 JAXP 全套流程

场景说明

飞翔科技的架构师 白歌 为团队封装了一个 XMLProcessor 工具类,支持:读 XML → XSD 验证 → DOM 修改 → XSLT 转换 → 写回文件。

集成代码

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.*;
import javax.xml.validation.*;
import org.w3c.dom.*;
import java.io.File;

public class XMLProcessor {

    // ① DOM 读取 + XSD 验证
    public static Document parseAndValidate(String xmlPath, String xsdPath)
            throws Exception {
        // 创建 Schema
        SchemaFactory sf = SchemaFactory.newInstance(
            "http://www.w3.org/2001/XMLSchema");
        Schema schema = sf.newSchema(new File(xsdPath));

        // 创建 DOM 解析器并绑定 Schema
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        dbf.setSchema(schema);  // 关键:绑定 XSD 验证

        DocumentBuilder db = dbf.newDocumentBuilder();

        // 自定义错误处理(解析失败不中断)
        db.setErrorHandler(new org.xml.sax.ErrorHandler() {
            public void warning(org.xml.sax.SAXParseException e) {
                System.out.println("警告: " + e.getMessage());
            }
            public void error(org.xml.sax.SAXParseException e) {
                System.out.println("错误: " + e.getMessage());
            }
            public void fatalError(org.xml.sax.SAXParseException e)
                    throws org.xml.sax.SAXException {
                throw e;  // 致命错误仍然抛出
            }
        });

        Document doc = db.parse(new File(xmlPath));
        System.out.println("XML 解析 + XSD 验证完成");
        return doc;
    }

    // ② XSLT 转换
    public static void transform(String xmlPath, String xsltPath,
                                  String outputPath) throws Exception {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer(
            new StreamSource(new File(xsltPath)));

        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

        transformer.transform(
            new StreamSource(new File(xmlPath)),
            new StreamResult(new File(outputPath))
        );

        System.out.println("XSLT 转换完成 → " + outputPath);
    }

    // ③ 保存 DOM 到文件
    public static void saveDocument(Document doc, String outputPath)
            throws Exception {
        Transformer tf = TransformerFactory.newInstance().newTransformer();
        tf.setOutputProperty(OutputKeys.INDENT, "yes");
        tf.transform(new DOMSource(doc), new StreamResult(new File(outputPath)));
        System.out.println("DOM 已保存 → " + outputPath);
    }

    public static void main(String[] args) throws Exception {
        // 完整流程:解析验证 → 修改 → 保存 → 转换
        Document doc = parseAndValidate("students.xml", "students.xsd");

        // 业务修改:给所有学生加 processDate 属性
        NodeList list = doc.getElementsByTagName("student");
        for (int i = 0; i < list.getLength(); i++) {
            ((Element) list.item(i)).setAttribute(
                "processDate", "2024-06-10");
        }

        saveDocument(doc, "students_verified.xml");
        transform("students_verified.xml",
                  "student_report.xsl",
                  "report.html");
    }
}

操作结果

白歌为团队封装了标准化的 XML 处理流程:

  1. parseAndValidate:读 XML 的同时用 XSD 验证,不合格直接报错
  2. transform:将验证后的 XML 用 XSLT 转为 HTML 报告
  3. saveDocument:保存 DOM 修改到文件

整个流程只依赖 JDK 标准库(javax.xml.*),无需第三方依赖。

易错场景

错误一:忘记 setNamespaceAware(true)

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// ❌ 默认不感知命名空间,XSD 验证失效
dbf.setSchema(schema);

// ✅ 必须先启用命名空间感知
dbf.setNamespaceAware(true);
dbf.setSchema(schema);

错误二:XSLT Transformer 未设置编码

// ❌ 中文可能乱码
Transformer t = TransformerFactory.newInstance().newTransformer(sheet);
t.transform(source, result);

// ✅ 显式设置编码
t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

面试考点

考点参考答案要点
JAXP 包含哪些主要 API?DOM(DocumentBuilder)、SAX(SAXParser)、StAX(XMLStreamReader)、XSLT(Transformer)、Validation(Schema/Validator)
JAXP 的 Factory 模式有什么好处?代码只依赖 javax.xml.* 接口,具体实现可插拔。通过 ServiceLoader 机制在运行时加载不同厂商的实现(Xerces/Woodstox/Saxon)
如何在 DOM 解析时同时进行 XSD 验证?①创建 SchemaFactory → Schema;②DocumentBuilderFactory.setSchema(schema);③setNamespaceAware(true);④builder.parse()
上一页
StAX 解析