概述
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. 创建一个子节点,节点名字叫streetElement 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 转为elementif (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;}@Overridepublic 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) {// 强转成elementElement e = (Element) n;// 使用element的getAttribute方法拿到studentidString 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;// 拿到学生IDString 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 blocke.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 {@Overridepublic void startDocument() throws SAXException {System.out.println("文档开始");}@Overridepublic void endDocument() throws SAXException {System.out.println("文档结束");}@Overridepublic void startElement(String uri, String localName, String qName, Attributes atts)throws SAXException {System.out.println("元素开始:" + qName);}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {System.out.println("元素结束:" + qName);}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {System.out.println("文本内容:" + new String(ch, start, length));}//------------以下采用空实现------------@Overridepublic void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {// TODO Auto-generated method stub}@Overridepublic void processingInstruction(String target, String data) throws SAXException {// TODO Auto-generated method stub}@Overridepublic void skippedEntity(String name) throws SAXException {// TODO Auto-generated method stub}@Overridepublic void setDocumentLocator(Locator locator) {// TODO Auto-generated method stub}@Overridepublic void startPrefixMapping(String prefix, String uri) throws SAXException {// TODO Auto-generated method stub}@Overridepublic 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 {@Overridepublic void startDocument() throws SAXException {System.out.println("文档开始");}@Overridepublic void endDocument() throws SAXException {System.out.println("文档结束");}@Overridepublic void startElement(String uri, String localName, String qName, Attributes atts)throws SAXException {System.out.println("元素开始:" + qName);}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {System.out.println("元素结束:" + qName);}@Overridepublic 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;@Overridepublic void startElement(String uri, String localName, String qName, Attributes atts)throws SAXException {if("City".equals(qName)) {count++;}isElement = true;}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {isElement = false;}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {if(count == 5 && isElement) {System.out.println("第5个区是:" + new String(ch, start, length));}}}
本文深入介绍了XML解析技术,包括DOM和SAX两种主要解析方式的特点和应用场景。详细讲解了使用JAXP进行DOM解析的方法,如文档对象获取、节点文本获取、节点遍历等,并通过具体案例展示了学生信息的XML文档操作。同时,介绍了SAX解析的基本概念和使用步骤。
1765

被折叠的 条评论
为什么被折叠?



