Java SAX 教程

Java SAX 教程

Java SAX 教程展示了如何使用 Java SAX API 来读取和验证 XML 文档。

SAX

SAX(XML 的简单 API)是事件驱动的算法,用于解析 XML 文档。 SAX 是文档对象模型(DOM)的替代方法。 在 DOM 读取整个文档以对 XML 进行操作的地方,SAX 解析器逐个节点读取 XML,发出解析事件,同时逐步遍历输入流。 SAX 独立于状态处理文档(元素的处理不依赖于之前的元素)。 SAX 解析器是只读的。

SAX 解析器更快并且需要更少的内存。 另一方面,DOM 更易于使用,并且有些任务(例如,排序元素,重新排列元素或查找元素)使用 DOM 更快。

SADK 解析器是 JDK 附带的,因此不需要下载依赖项。

Java SAX 解析示例

在下面的示例中,我们使用 SAX 解析器读取 XML 文件。

org.codehaus.mojo

exec-maven-plugin

1.6.0

com.zetcode.JavaReadXmlSaxEx

我们使用exec-maven-plugin从 Maven 执行 Java 主类。

users.xml

Peter

Brown

programmer

Martin

Smith

accountant

Lucy

Gordon

teacher

我们将阅读此 XML 文件。

User.java

package com.zetcode;

public class User {

int id;

private String firstName;

private String lastName;

private String occupation;

public User() {

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getFirstName() {

return firstName;

}

public void setFirstName(String firstName) {

this.firstName = firstName;

}

public String getLastName() {

return lastName;

}

public void setLastName(String lastName) {

this.lastName = lastName;

}

public String getOccupation() {

return occupation;

}

public void setOccupation(String occupation) {

this.occupation = occupation;

}

@Override

public String toString() {

StringBuilder builder = new StringBuilder();

builder.append("User{").append("id=").append(id)

.append(", firstName=").append(firstName)

.append(", lastName=").append(lastName)

.append(", occupation=").append(occupation).append("}");

return builder.toString();

}

}

这是用户 bean。 它将保存来自 XML 节点的数据。

MyRunner.java

package com.zetcode;

import java.io.File;

import java.io.IOException;

import java.nio.file.Paths;

import java.util.List;

import java.util.logging.Level;

import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class MyRunner {

private SAXParser createSaxParser() {

SAXParser saxParser = null;

try {

SAXParserFactory factory = SAXParserFactory.newInstance();

saxParser = factory.newSAXParser();

return saxParser;

} catch (ParserConfigurationException | SAXException ex) {

Logger lgr = Logger.getLogger(MyRunner.class.getName());

lgr.log(Level.SEVERE, ex.getMessage(), ex);

}

return saxParser;

}

public List parseUsers() {

MyHandler handler = new MyHandler();

String fileName = "src/main/resources/users.xml";

File xmlDocument = Paths.get(fileName).toFile();

try {

SAXParser parser = createSaxParser();

parser.parse(xmlDocument, handler);

} catch (SAXException | IOException ex) {

Logger lgr = Logger.getLogger(MyRunner.class.getName());

lgr.log(Level.SEVERE, ex.getMessage(), ex);

}

return handler.getUsers();

}

}

MyRunner创建一个 SAX 解析器并启动解析。 parseUsers返回User对象列表中的解析数据。

SAXParserFactory factory = SAXParserFactory.newInstance();

saxParser = factory.newSAXParser();

从SAXParserFactory获得SAXParser。

SAXParser parser = createSaxParser();

parser.parse(xmlDocument, handler);

我们使用parse()方法解析文档。 方法的第二个参数是处理程序对象,其中包含事件处理程序。

MyHandler.java

package com.zetcode;

import java.util.ArrayList;

import java.util.List;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

public class MyHandler extends DefaultHandler {

private List users = new ArrayList<>();

private User user;

private boolean bfn = false;

private boolean bln = false;

private boolean boc = false;

@Override

public void startElement(String uri, String localName,

String qName, Attributes attributes) throws SAXException {

if ("user".equals(qName)) {

user = new User();

int id = Integer.valueOf(attributes.getValue("id"));

user.setId(id);

}

switch (qName) {

case "firstname":

bfn = true;

break;

case "lastname":

bln = true;

break;

case "occupation":

boc = true;

break;

}

}

@Override

public void characters(char[] ch, int start, int length) throws SAXException {

if (bfn) {

user.setFirstName(new String(ch, start, length));

bfn = false;

}

if (bln) {

user.setLastName(new String(ch, start, length));

bln = false;

}

if (boc) {

user.setOccupation(new String(ch, start, length));

boc = false;

}

}

@Override

public void endElement(String uri, String localName,

String qName) throws SAXException {

if ("user".equals(qName)) {

users.add(user);

}

}

public List getUsers() {

return users;

}

}

在MyHandler类中,我们具有事件处理程序的实现。

public class MyHandler extends DefaultHandler {

处理程序类必须从具有事件方法的DefaultHandler扩展。

@Override

public void startElement(String uri, String localName,

String qName, Attributes attributes) throws SAXException {

if ("user".equals(qName)) {

user = new User();

int id = Integer.valueOf(attributes.getValue("id"));

user.setId(id);

}

switch (qName) {

case "firstname":

bfn = true;

break;

case "lastname":

bln = true;

break;

case "occupation":

boc = true;

break;

}

}

当解析器开始解析新元素时,将调用startElement()方法。 如果元素为<user>,我们将创建一个新用户。 对于其他类型的元素,我们设置布尔值。

@Override

public void characters(char[] ch, int start, int length) throws SAXException {

if (bfn) {

user.setFirstName(new String(ch, start, length));

bfn = false;

}

if (bln) {

user.setLastName(new String(ch, start, length));

bln = false;

}

if (boc) {

user.setOccupation(new String(ch, start, length));

boc = false;

}

}

当解析器在元素内部遇到文本时,将调用characters()方法。 根据布尔变量,我们设置用户属性。

@Override

public void endElement(String uri, String localName,

String qName) throws SAXException {

if ("user".equals(qName)) {

users.add(user);

}

}

在<user>元素的末尾,我们将用户对象添加到用户列表中。

JavaReadXmlSaxEx.java

package com.zetcode;

import java.util.List;

public class JavaReadXmlSaxEx {

public static void main(String[] args) {

MyRunner runner = new MyRunner();

List lines = runner.parseUsers();

lines.forEach(System.out::println);

}

}

JavaReadXmlSaxEx启动应用。 它将解析任务委托给MyRunner。 最后,检索到的数据将打印到控制台。

$ mvn exec:java -q

User{id=1, firstName=Peter, lastName=Brown, occupation=programmer}

User{id=2, firstName=Martin, lastName=Smith, occupation=accountant}

User{id=3, firstName=Lucy, lastName=Gordon, occupation=teacher}

这是示例的输出。

Java SAX 验证示例

以下示例使用 XSD 语言来验证 XML 文件。 XSD(XML 架构定义)是所有 XML 文档和数据的当前标准架构语言。 (还有其他替代的模式语言,例如 DTD 和 RELAX NG。)XSD 是 XML 文档必须遵循的一组规则,以便根据该模式被视为有效。

users.xsd

xmlns:xs="http://www.w3.org/2001/XMLSchema"

elementFormDefault="qualified">

这是用于验证用户的 XSD 文件。 例如,它声明<user>元素必须在<users>元素之内,或者<user>的id属性必须是且是整数,并且是强制性的。

JavaXmlSchemaValidationEx.java

package com.zetcode;

import java.io.File;

import java.io.IOException;

import java.io.Reader;

import java.nio.file.Files;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.util.logging.Level;

import java.util.logging.Logger;

import javax.xml.XMLConstants;

import javax.xml.transform.sax.SAXSource;

import javax.xml.validation.Schema;

import javax.xml.validation.SchemaFactory;

import javax.xml.validation.Validator;

import org.xml.sax.InputSource;

import org.xml.sax.SAXException;

public class JavaXmlSchemaValidationEx {

public static void main(String[] args) {

File xsdFile = new File("src/main/resources/users.xsd");

try {

Path xmlPath = Paths.get("src/main/resources/users.xml");

Reader reader = Files.newBufferedReader(xmlPath);

String schemaLang = XMLConstants.W3C_XML_SCHEMA_NS_URI;

SchemaFactory factory = SchemaFactory.newInstance(schemaLang);

Schema schema = factory.newSchema(xsdFile);

Validator validator = schema.newValidator();

SAXSource source = new SAXSource(new InputSource(reader));

validator.validate(source);

System.out.println("The document was validated OK");

} catch (SAXException ex) {

Logger lgr = Logger.getLogger(JavaXmlSchemaValidationEx.class.getName());

lgr.log(Level.SEVERE, "The document failed to validate");

lgr.log(Level.SEVERE, ex.getMessage(), ex);

} catch (IOException ex) {

Logger lgr = Logger.getLogger(JavaXmlSchemaValidationEx.class.getName());

lgr.log(Level.SEVERE, ex.getMessage(), ex);

}

}

}

该示例使用users.xsd模式来验证users.xml文件。

String schemaLang = XMLConstants.W3C_XML_SCHEMA_NS_URI;

SchemaFactory factory = SchemaFactory.newInstance(schemaLang);

Schema schema = factory.newSchema(xsdFile);

使用SchemaFactory,我们为我们的模式定义选择 W3C XML 模式。 换句话说,我们的自定义架构定义还必须遵守某些规则。

Validator validator = schema.newValidator();

从架构生成一个新的验证器。

SAXSource source = new SAXSource(new InputSource(reader));

validator.validate(source);

我们根据提供的模式验证 XML 文档。

} catch (SAXException ex) {

Logger lgr = Logger.getLogger(JavaXmlSchemaValidationEx.class.getName());

lgr.log(Level.SEVERE, "The document failed to validate");

lgr.log(Level.SEVERE, ex.getMessage(), ex);

}

默认情况下,如果文档无效,则抛出SAXException。

📚 相关推荐

电动汽车充一次电需多少度?充电费用怎么计算?一文详细解析
农业银行无卡存款多久到账?
梦幻西游房子休息加多少体活 梦幻西游体活多久满
直播APP的测试
100大卡米粉能吃多少?
打造世界攻略集