解析xml
xml解析的简介(重点)


sax解析的原理
* 解析xml有两种技术 dom 和 sax
* 根据xml的层级结构在内存中分配一个树形结构
** 把xml中标签、属性、文本封装成对象
sax方式:事件驱动,边读边解析
* 在javax.xml.parsers包里面
** SAXParser
此类的实例可以从 SAXParserFactory.newSAXParser()方法获取
- parse(File f,DefaultHandler dh)
* 两个参数
** 第一个参数:xml的路径
** 事件处理器
** SAXParserFactory
实例newInstance()方法中获取
* 分析sax执行的过程
- 当解析开始标签时,自动执行startElement方法
- 当解析到文本的时候,自动解析characters方法
- 当解析到结束标签的时候,自动执行endElement方法
jaxp解析xml
使用jaxp的sax方式解析xml
* sax方式不能实现增删改操作,只能做查询操作
* 打印整个文档
** 执行parse方法,第一个参数是xml的路径,第二个参数是事件处理器
* 创建一个类,继承事件处理器的类
* 重写里面的三个方法
** 获取所有的name元素的值
* 定义一个成员变量 flag = false
* 判断开始方法是否是name元素,如果是name元素,把false改成true
*如果flag值是true,在characters方法中打印内容
* 当执行到结束方法的时候,把flag值设置为false
** 获取第一个name的值
* 定义一个成员变量的值 idx=1
* 在结束方法的时候,idx+1 idx++
* 想要打印出第一个元素的值,
- 在characters方法里面判断
-- 判断flag=true 并且 idx=1,再打印内容
public class TestSax { public static void main(String[] args) throws Exception { // 创建解析器工厂 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); // 创建解析器 SAXParser saxParser = saxParserFactory.newSAXParser(); // 执行parse方法 saxParser.parse("src/person.xml", new MyDefault2()); } } // 获取所有name元素的值 class MyDefault2 extends DefaultHandler { boolean flag = false; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 判断qName是否是name元素 if ("name".equals(qName)) { flag = true; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if(flag == true) { System.out.println(new String(ch,start,length)); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //把flag设置成false,表示name元素结束 if("name".equals(qName)) { flag = false; } } } // 打印整个文档的内容 class MyDefault1 extends DefaultHandler { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.print("<" + qName + ">"); } @Override public void characters(char[] ch, int start, int length) throws SAXException { System.out.print(new String(ch, start, length)); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.print("</" + qName + ">"); }
使用jaxp的dom方式解析xml
jaxp查询节点
private static void selectAll() throws Exception { // 创建解析器工厂 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); // 根据解析器工厂得到解析器 DocumentBuilder builder = builderFactory.newDocumentBuilder(); // 解析xml得到document Document document = builder.parse("src/person.xml"); // 得到所有的name元素 NodeList list = document.getElementsByTagName("name"); // 遍历集合 for (int i = 0; i < list.getLength(); i++) { Node name = list.item(i); String s = name.getTextContent(); System.out.println(s); } }
jaxp添加节点
// 添加节点 private static void addOne() throws Exception{ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = builderFactory.newDocumentBuilder(); Document document = builder.parse("src/person.xml"); NodeList list = document.getElementsByTagName("p1"); Node p1 = list.item(0); Element sex = document.createElement("sex"); Text text = document.createTextNode("nan"); sex.appendChild(text); p1.appendChild(sex); //回写xml TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(new DOMSource(document), new StreamResult("src/person.xml")); }
jaxp修改节点
添加一个setTextContent方法即可
jaxp删除节点
获取要删除节点的父节点,利用其父节点删除该节点,只要内容发生变化都必须回写xml
jaxp遍历节点
获取节点的子节点,然后利用递归调用完成所有子节点的遍历
// 遍历节点 private static void listElement() throws Exception { DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = builderFactory.newDocumentBuilder(); Document document = builder.parse("src/person.xml"); // 编写一个方法来遍历节点 list1(document); } private static void list1(Node node) { // 判断是元素类型才打印 if (node.getNodeType() == Node.ELEMENT_NODE) { System.out.println(node.getNodeName()); } // 得到node下面的子节点 NodeList list = node.getChildNodes(); // 遍历list for (int i = 0; i < list.getLength(); i++) { // 得到lsit下面的节点 Node node1 = list.item(i); // 使用递归调用实现继续得到子节点的方法 list1(node1); } }
dom4j解析XML
* dom4j是一个组织,针对xml解析,提供解析器dom4j
* dom4j不是javase的一部分,所以需要导包
* 达到document
SAXReader reader = new SAXReader();
Document document = reader.read(url);
* document的父节点是Node
* 如果在document里面找不到想要的方法,到Node里面去找
* document里面的方法 getRootElement() 获取到根节点 返回的是Element
* Element也是一个接口,父接口是Node
- Element和Node里面方法
** getParent() 添加父节点
** addElement 添加标签
使用dom4j实现查询操作
查询所有name元素里面的值
1、创建解析器
2、得到document
3、得到根节点 getRootElement() 返回Element
4、得到所有的p1标签
* element("p1") 返回list集合
** 表示获取标签下面第一个子标签
** qname:标签的名称
* element(qname)
** 获取标签下面的所有子标签
* elements()
** 获取标签下面的所有的一层标签
5、得到name
* 在p1下面执行 element("name")方法 返回Element
6、得到name里面的值
* getText方法得到值
public class TestDom4j { public static void main(String[] args) throws Exception { selectName(); } public static void selectName() throws Exception { //创建解析器 SAXReader saxReader = new SAXReader(); //得到document Document document = saxReader.read("src/person.xml"); //得到根节点 Element root = document.getRootElement(); //得到p1 List<Element> list = root.elements(); //便利list for(Element element : list) { Element name1 = element.element("name"); String s = name1.getText(); System.out.println(s); } } }
查询第一个name元素的值
public static void selectOne() throws Exception { // 创建解析器 SAXReader saxReader = new SAXReader(); // 得到document Document document = saxReader.read("src/person.xml"); // 得到根节点 Element root = document.getRootElement(); // 得到p1 Element p1 = root.element("p1"); // 得到第一个name Element name1 = p1.element("name"); // 得到name1里面的值 String s = name1.getText(); System.out.println(s); }
使用dom4j实现添加操作
在第一个p1标签末尾添加一个元素<sex>nv</sex>
// 在第一个p1标签下添加一个sex元素 public static void addSex() throws Exception { // 创建解析器 SAXReader saxReader = new SAXReader(); // 获取document Document document = saxReader.read("src/person.xml"); // 得到根节点 Element root = document.getRootElement(); // 获取第一个p1 Element p1 = root.element("p1"); // 在p1下面添加元素 Element sex = p1.addElement("sex"); // 在添加之后的元素下面添加文本 sex.addText("nv"); // 回写xml OutputFormat format = OutputFormat.createPrettyPrint();//可以有缩进的效果 XMLWriter xmlWrite = new XMLWriter(new FileOutputStream("src/person.xml"), format); xmlWrite.write(document); xmlWrite.close(); }
在第一个p1标签下的age之前添加school标签
// 在第一个标签p1下面的age之前添加<school></school> public static void addSchool() throws Exception { // 创建解析器 SAXReader saxReader = new SAXReader(); // 获取document Document document = saxReader.read("src/person.xml"); // 得到根节点 Element root = document.getRootElement(); // 得到第一个p1 Element p1 = root.element("p1"); // 获取第一个p1下面的所有元素 List<Element> list = p1.elements(); // // 获取p1下面的第一个age元素 // Element age1 = p1.element("age"); // // 获取age在列表里面的位置 // int index = age1.indexOf(p1); // 创建一个school元素 // Element school= document.addElement("school"); Element school = DocumentHelper.createElement("school"); // 创建文本 school.setText("CDNU"); // 在特定位置添加元素 // list.add(index - 1, school); list.add(1, school); // 回写xml OutputFormat format = OutputFormat.createPrettyPrint();// 可以有缩进的效果 XMLWriter xmlWrite = new XMLWriter(new FileOutputStream("src/person.xml"), format); xmlWrite.write(document); xmlWrite.close(); }
dom4j里面封装方法的操作
* 将得到document的操作和回写xml的操作封装成方法,还可将传递的文件路径封装成一个常量
public class dom4jUntils { public static final String PATH = "src/person.xml"; //返回document public static Document getDocument(String path) { try { //创建解析器 SAXReader reader = new SAXReader(); //得到documen Document document = reader.read(path); return document; }catch (Exception e) { e.printStackTrace(); } return null; } //回写xml的方法 public static void xmlWriters(String path,Document document) { try { OutputFormat format = OutputFormat.createPrettyPrint();// 可以有缩进的效果 XMLWriter xmlWrite = new XMLWriter(new FileOutputStream("src/person.xml"), format); xmlWrite.write(document); xmlWrite.close(); }catch (Exception e) { e.printStackTrace(); } } }
dom4j实现修改操作
// 修改第一个p1下面的age标签的值为33 public static void modifyAge() throws Exception { Document document = dom4jUntils.getDocument(dom4jUntils.PATH); Element root = document.getRootElement(); Element p1 = root.element("p1"); Element age = p1.element("age"); age.setText("33"); dom4jUntils.xmlWriters(dom4jUntils.PATH, document); }
dom4j实现获取标签属性值
// 获取p1标签id1的属性值 public static void getAttribute() throws Exception { Document document = dom4jUntils.getDocument(dom4jUntils.PATH); Element root = document.getRootElement(); Element p1 = root.element("p1"); String value = p1.attributeValue("id1"); System.out.println(value); }
dom4j支持XPATH的操作
XPATH的简介
* 可以支持获取到某个元素
* 第一种形式
/AAA/DDD/BBB :表示一层一层的,AAA下面DDD下面的BBB
* 第二种形式
//BBB :表示和这个名称相同,只要是BBB都得到
* 第三种形式
/* :所有元素
* 第四种形式
BBB[1] :表示第一个BBB元素
BBB[last()] :表示最后一个BBB元素
* 第五种形式
//BBB[@id] :表示只要是BBB属性上面有id属性都得到
* 第六种形式
//BBB[@id='b1'] :元素名称是bbb,并且其id属性的值是b1
*** dom4j提供两个方法,用来支撑XPATH
- selectNodes("xpath表达式"); 获取多个节点
- selectsingleNode("xpath表达式"); 获取单个节点
查询xml中所有name元素的值
public static void getName() throws Exception { // 得到document Document document = dom4jUntils.getDocument(dom4jUntils.PATH); List<Node> list = document.selectNodes("//name"); for (Node node : list) { String s = node.getText(); System.out.println(s); } }
实现简单的学生管理系统
* 使用xml当做数据库,存储学生信息
* 创建一个xml文件,写一些学生信息
package cn.zzr.service; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import cn.cmlx.dom4jutils.dom4jUntils; import cn.zzr.vo.Student; public class StuService { //增加 public static void addStudent(Student student) throws Exception { //创建解析器 SAXReader saxReader = new SAXReader(); Document document = saxReader.read("src/student.xml"); Element root = document.getRootElement(); Element stu = root.addElement("stu"); Element id1 = stu.addElement("id"); Element name1 = stu.addElement("name"); Element age1 = stu.addElement("age"); id1.setText(student.getId()); name1.setText(student.getName()); age1.setText(student.getAge()); //回写xml dom4jUntils.xmlWriters("src/student.xml", document); } //删除 public static void delStudent(String id) throws Exception{ SAXReader saxReader = new SAXReader(); Document document = saxReader.read("src/student.xml"); Element root = document.getRootElement(); //获取所有的id List<Node> list = root.selectNodes("id"); for(Node node : list) { String idv = node.getText(); if(idv.equals(id)) { Element stu = node.getParent(); Element student = stu.getParent(); student.remove(stu); } } //回写xml dom4jUntils.xmlWriters("src/student.xml", document); } //查找 public static Student selStudent(String id) throws Exception{ Student student = new Student(); SAXReader saxReader = new SAXReader(); Document document = saxReader.read("src/student.xml"); //获取所有的id List<Node> list = document.selectNodes("//id"); for(Node node : list) { String idv = node.getText(); if(idv.equals(id)) { Element stu = node.getParent(); String namev = stu.element("name").getText(); String agev = stu.element("age").getText(); student.setId(idv); student.setName(namev); student.setAge(agev); } } return student; } }
package cn.zzr.vo; public class Student { private String id; private String name; private String age; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
<?xml version="1.0" encoding="UTF-8"?>
<student>
<stu>
<id>111</id>
<name>zq</name>
<age>11</age>
</stu>
<stu>
<id>222</id>
<name>cmlx</name>
<age>22</age>
</stu>
</student>
package cn.zzr.stutest; import cn.zzr.service.StuService; import cn.zzr.vo.Student; public class StudentTest { public static void main(String[] args) throws Exception { // testAdd(); // testDel(); testSel(); } public static void testAdd() throws Exception { Student student = new Student(); student.setId("333"); student.setName("zzr"); student.setAge("33"); StuService.addStudent(student); } public static void testDel() throws Exception { StuService.delStudent("333"); } public static void testSel() throws Exception { Student stu = StuService.selStudent("111"); System.out.println(stu.toString()); } }

浙公网安备 33010602011771号