[学习笔记]XML解析之JAXP

来源:互联网 发布:源码客栈 编辑:程序博客网 时间:2024/05/17 08:58

概述

XML解析方式

DOM

Document Object Model,文档对象模型。这种方式是W3C推荐的处理XML的一种方式。
Dom解析将XML文件全部读入并生成DOM树,所有的XML标签,属性和文本内容均为DOM树上的节点,并采用节点操作的方式可以对任意一个元素进行增删改查。

SAX

Simple API for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。
SAX解析是基于事件驱动的XML解析方式,该方式的工作需要依赖事件处理接口,根据发生的事件的发生来针对性的采取对应操作。由于该方式产生操作不需要加载全部XML文件,所以对于超大的XML文件的解析效率较高。

XML解析开发包

JAXP:是SUN公司推出的解析标准实现。
Dom4J:是开源组织推出的一种解析开发包,较为常用。
JDom:是开源组织推出的一种解析开发包。

JAXP

概述

JAXP(Java API for XML Processing)开发包是JavaSE的一部分,它由以下几个包及其子包组成:
org.w3c.dom:提供DOM方式解析XML的标准接口。
org.xml.sax:提供SAX方式解析XML的标准接口。
javax.xml:提供了解析XML文档的类。
javax.xml.parsers:提供了对XML文档解析工厂类,通过工厂类(DocumentBuilderFactory、SAXParserFactory)可以得到对XML文档进行解析的DOM和SAX解析器对象。

使用DOM方式解析XML文档

1. 常用API

  • 解析器工厂类:DocumentBuilderFactory
  • 解析器:DocumentBuilder
  • 文档对象:Document
  • 节点对象:Node
  • 节点集合:NodeList
  • 元素:Element
  • 修改文件工厂类:TransformerFactory
  • 保存文件:Transformer

2. 解析XML获取文档对象

public static void main(String[] args) {
DocumentBuilderFactory factory = null;
DocumentBuilder builder = null;
Document document = null;
try {
// 1. 先拿到解析器的工厂类
factory = DocumentBuilderFactory.newInstance();
// 2. 拿到解析器
builder = factory.newDocumentBuilder();
// 3. 解析XML,获取文档对象
document = builder.parse("src/LocalList.xml");
} catch (Exception e) {
e.printStackTrace();
}
}

3. 获取节点文本

public static void getNodeText(Document document) {
// 1. 先拿到元素名称为city的所有节点
NodeList nlist = document.getElementsByTagName("City");
// 2. 找到指定位置的节点
Node n = nlist.item(7);
// 3. 打印文本内容
System.out.println("Node Text is " + n.getTextContent());
}
注意:获取节点文本包括暗部和所有的子节点。

4. 递归节点遍历

public static void getAllNodeText(Document document) {
// 1. 获得需要遍历的节点
Node node = document.getElementsByTagName("State").item(0);
// 2. 递归调用的开始
recursion(node);
}
 
private static void recursion(Node node) {
// 1. 只有元素节点才打印
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println("Node Name is " + node.getTextContent());
}
// 2. 拿到当前节点的所有子节点
NodeList nlist = node.getChildNodes();
for (int i = 0; i < nlist.getLength(); i++) {
Node n = nlist.item(i);
recursion(n);
}
}

5. 保存更改到文件

public static void save(Document document) throws Exception {
// 1. 拿到保存文件对象的工厂类
TransformerFactory tfactory = TransformerFactory.newInstance();
// 2. 拿到保存文件的对象
Transformer tf = tfactory.newTransformer();
// 3. 保存文件
// DOMSource 用来指定 domcument 对象
tf.transform(new DOMSource(document), new StreamResult("src/LocalList.xml"));
}

6. 修改节点文本内容

public static void modifyNodeText(Document document) throws Exception {
// 1. 拿到street节点
Node node = document.getElementsByTagName("street").item(0);
// 2. 设置文本内容
node.setTextContent("和平门大街");
// 以上并没有真正的取保存文件,只是修改了内存中数据
 
save(document);
}

7. 添加子节点

public static void createChildNode(Document document) throws Exception {
// 1. 拿到要添加位置的父节点
Node node = document.getElementsByTagName("City").item(2);
// 2. 创建一个子节点,节点名字叫street
Element e = document.createElement("street");// 创建了<street></street>
e.setTextContent("前门大街");// <street>前门大街</street>
// 3. 添加到列表末尾
node.appendChild(e);
 
save(document);
}

8. 添加兄弟节点

public static void createNode(Document document) throws Exception {
// 1. 拿到要添加的指定位置的后一个
Node node = document.getElementsByTagName("City").item(2);
// 2. 创建节点
Element e = document.createElement("City");
e.setTextContent("崇文区");
// 3. 使用父节点去在子节点之前添加新节点
node.getParentNode().insertBefore(e, node);
 
save(document);
}

9. 删除节点

public static void removeNode(Document document) throws Exception {
// 1. 获取要删除的节点
Node node = document.getElementsByTagName("street").item(0);
// 2. 找到他的父节点,删除子节点
node.getParentNode().removeChild(node);
 
save(document);
}

10. 设置节点属性

public static void createAttribute(Document document) throws Exception {
// 1. 拿到[崇文区]这个节点
Node node = document.getElementsByTagName("City").item(2);
// 2. 将node 转为element
if (node != null && node instanceof Element) {
Element e = (Element) node;
e.setAttribute("Code", "103");
}
save(document);
}

11. 案例

学生信息存储体系
Student.java
package com.itheima.beans;
public class Student {
 
private String classid;
private String studentid;
private String name;
private String sex;
private String score;
 
public Student() {}
 
public Student(String classid, String studentid, String name, String sex, String score) {
this.classid = classid;
this.studentid = studentid;
this.name = name;
this.sex = sex;
this.score = score;
}
 
public String getClassid() {
return classid;
}
 
public void setClassid(String classid) {
this.classid = classid;
}
 
public String getStudentid() {
return studentid;
}
 
public void setStudentid(String studentid) {
this.studentid = studentid;
}
 
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
 
public String getSex() {
return sex;
}
 
public void setSex(String sex) {
this.sex = sex;
}
 
public String getScore() {
return score;
}
 
public void setScore(String score) {
this.score = score;
}
 
@Override
public String toString() {
return "Student [classid=" + classid + ", studentid=" + studentid + ", name=" + name + ", sex="
+ sex + ", score=" + score + "]";
}
}

JAXP的工具类,包括文档获取方法和保存方法
JaxpUtils.java
package com.itheima.utils;
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
 
import org.w3c.dom.Document;
 
// JAXP的工具类
public class JaxpUtils {
 
// 获取document对象
public static Document getDocument() {
DocumentBuilderFactory factory = null;
DocumentBuilder builder = null;
Document document = null;
try {
factory = DocumentBuilderFactory.newInstance();
builder = factory.newDocumentBuilder();
document = builder.parse("src/com/itheima/db/Students.xml");
} catch (Exception e) {
throw new RuntimeException(" Can not get document !");
}
return document;
}
 
// 保存文件
public static void saveXML(Document document) {
TransformerFactory factory = null;
Transformer tf = null;
try {
factory = TransformerFactory.newInstance();
tf = factory.newTransformer();
tf.transform(new DOMSource(document), new StreamResult("src/com/itheima/db/Students.xml"));
} catch (Exception e) {
throw new RuntimeException("Save XML failed ");
}
}
}

对学生信息XML文档的操作
StudentDao.java
package com.itheima.dao.impl;
 
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
import com.itheima.beans.Student;
import com.itheima.utils.JaxpUtils;
 
public class StudentDAO {
 
// 添加用户
public boolean save(Student s) {
// 拿到document对象
Document document = JaxpUtils.getDocument();
// 1. 创建Student节点
Element studentE = document.createElement("Student");
// 2. 添加student节点的属性
studentE.setAttribute("classid", s.getClassid());
studentE.setAttribute("studentid", s.getStudentid());
// 3. 创建name节点
Element nameE = document.createElement("name");
// 4. 给name节点添加文本内容
nameE.setTextContent(s.getName());
// 5. 创建sex节点
Element sexE = document.createElement("sex");
// 6. 给sex节点添加文本内容
sexE.setTextContent(s.getSex());
// 7. 创建score节点
Element scoreE = document.createElement("score");
// 8. 给score添加文本内容
scoreE.setTextContent(s.getScore());
// 9. 逐级添加到节点上
studentE.appendChild(nameE);
studentE.appendChild(sexE);
studentE.appendChild(scoreE);
// 10. 拿到Students(根节点)节点
Node node = document.getElementsByTagName("Students").item(0);
// 11. 把 studentE添加到Students的节点上
node.appendChild(studentE);
// 12. 将添加的内容保存到xml文件中
JaxpUtils.saveXML(document);
return true;
}
 
// 删除用户
public boolean remove(String studentid) {
boolean result = false;
// 1. 拿到所有的学生信息
Document document = JaxpUtils.getDocument();
NodeList nlist = document.getElementsByTagName("Student");
// 2. 遍历nlist列表
for (int i = 0; i < nlist.getLength(); i++) {
// 拿到每一个节点
Node n = nlist.item(i);
// 判断n是不是属于元素节点,并且属于element类型
if (n.getNodeType() == Node.ELEMENT_NODE && n instanceof Element) {
// 强转成element
Element e = (Element) n;
// 使用element的getAttribute方法拿到studentid
String sid = e.getAttribute("studentid");
if (sid.equals(studentid)) {
// 删除当前节点,使用父节点操作
e.getParentNode().removeChild(e);
JaxpUtils.saveXML(document);
result = true;
break;
}
}
}
return result;
}
 
// 查询成绩
public String getScoreByStudentid(String studentid) {
String score = "";
// 1. 拿到所有的学生信息
Document document = JaxpUtils.getDocument();
NodeList nlist = document.getElementsByTagName("Student");
// 2. 遍历nlist列表
for (int i = 0; i < nlist.getLength(); i++) {
// 拿到每一个节点
Node n = nlist.item(i);
// 判断n是不是属于元素节点,并且属于element类型
if (n.getNodeType() == Node.ELEMENT_NODE && n instanceof Element) {
Element e = (Element) n;
// 拿到学生ID
String sid = e.getAttribute("studentid");
// 判断学生id跟传进来的参数是否一致
if (sid.equals(studentid)) {
NodeList nl = e.getChildNodes();
for (int j = 0; j < nl.getLength(); j++) {
Node node = nl.item(j);
if (node.getNodeType() == Node.ELEMENT_NODE && "score".equals(node.getNodeName())) {
score = node.getTextContent();
break;
}
}
}
}
}
return score;
}
}

使用SAX方式解析XML文档

1. 常用API

  • SAX解析器工厂类:SAXParserFactory
  • SAX解析器:SAXParser
  • XML读取类:XMLReader
  • 事件处理接口:ContentHandler
  • 默认事件处理适配器类:DefaultHandler

2. 获取SAX解析并设置事件处理器

注意:必须先设置时间处理器,后设置XML文件源
public static void main(String[] args) {
try {
// 获取SAX解析器的工厂类
SAXParserFactory factory = SAXParserFactory.newInstance();
// 获取SAX解析器
SAXParser sax = factory.newSAXParser();
// 获取XMLReader的读取对象
XMLReader reader = sax.getXMLReader();
// 设置事件处理器
reader.setContentHandler(new DemoHandler());
// 设置xml文件源
reader.parse("src/LocalList.xml");
} catch (ParserConfigurationException | SAXException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

3. 通过直接实现事件处理接口定义事件处理器

DemoHandler.java
package xml.sax.handler;
 
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
 
public class DemoHandler implements ContentHandler {
 
@Override
public void startDocument() throws SAXException {
System.out.println("文档开始");
}
 
@Override
public void endDocument() throws SAXException {
System.out.println("文档结束");
}
 
@Override
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException {
System.out.println("元素开始:" + qName);
}
 
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("元素结束:" + qName);
}
 
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println("文本内容:" + new String(ch, start, length));
}
//------------以下采用空实现------------
 
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
 
}
 
@Override
public void processingInstruction(String target, String data) throws SAXException {
// TODO Auto-generated method stub
 
}
 
@Override
public void skippedEntity(String name) throws SAXException {
// TODO Auto-generated method stub
 
}
 
@Override
public void setDocumentLocator(Locator locator) {
// TODO Auto-generated method stub
 
}
 
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
// TODO Auto-generated method stub
 
}
 
@Override
public void endPrefixMapping(String prefix) throws SAXException {
// TODO Auto-generated method stub
 
}
}

4. 通过继承事件处理默认适配器定义事件处理器

DemoAdapterHandler.java
package xml.sax.handler;
 
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
 
public class DemoAdapterHandler extends DefaultHandler {
 
@Override
public void startDocument() throws SAXException {
System.out.println("文档开始");
}
 
@Override
public void endDocument() throws SAXException {
System.out.println("文档结束");
}
 
@Override
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException {
System.out.println("元素开始:" + qName);
}
 
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("元素结束:" + qName);
}
 
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println("文本内容:" + new String(ch, start, length));
}
}

5. 案例

元素计数及简单逻辑
DemoAdapterHandler.java
package xml.sax.handler;
 
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
 
public class DemoAdapterHandler extends DefaultHandler {
 
int count = 0;
boolean isElement = false;
@Override
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException {
if("City".equals(qName)) {
count++;
}
isElement = true;
}
 
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
isElement = false;
}
 
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if(count == 5 && isElement) {
System.out.println("第5个区是:" + new String(ch, start, length));
}
}
}

0 0
原创粉丝点击