第十四次总结 XML(DOM、SAX)
- XML的发展经历标记语言有哪些?
- 什么是XML解析?
- Java中解析XML的工具?
- 如何使用DOM方式修改xml数据?
- 如何通过SAX方式获得xml数据
1.XML的发展经历标记语言有哪些?
| GML | 通用的标记语言,为了解决程序之间数据传输格式问题的 |
| SGML | 标准的通用标记语言 万维网联盟 |
| HTML | 超文本标记语言 |
| XML: Xtensible Markup Language | 可扩展标记语言 |
| xHTML | 可扩展的超文本标记语言 |
| HTML5 | 可扩展的超文本标记语言 |
2.什么是XML解析?
可扩展的标记语言
用来解决数据传输的格式问题
用法:
1.从xml数据中提取需要的内容
2.将数据转换成xml格式
XML的解析标准
DOM W3C官方的标准
Sax XML社区标准
DOM Documnet Object Model 文档对象模型
DOM的基本思想:
将整个XML数据转换成一个树形对象[Document对象]
将XML中的标签,属性,文本都作为一个结点对象
在解析XML的时候,先将整个xml一次性读入到内存中,
封装成树对象
再对树上的结点进行操作[增删改查]
XML的数据类型:标签 属性 文本
整个XML文档是一个 Documnet对象
标签是一个 Element对象
属性是一个 Attr 对象
文本是一个 Text对象
Document Element Attr Text都是一个节点,是Node类的子类
.XML数据的标准格式
xml必须包含头声明
有且只有一对根标签
标签的开始和结束必须一样,包括大小写
<span>内容</span>
如果标签中不包含子元素,就可以写成单标签
<span />
DOM方式解析的优点:
由于所有的结点都在内存的Document对象中,支持随机访问
DOM方式解析的缺点:
由于所有的数据是一次性读入到内存中的,对于比较大的xml数据,非常占内存
Sax: Simple API for XML
简单的xml解析API
API:Application Program Interface 应用程序编程接口
俗称:已经写好的工具类
Sax的基本思想:
顺序解析,事件驱动
一边读取数据,一边进行解析,在读取数据的时候会触发一定的事件,每触发一次,就可以做一次处理
继承DefaultHandler
需要重写的方法
startDocument 开始文档
endDocument 文档结束
startElement 开始标签
endElement 结束标签
characters 字符处理
3.Java中解析XML的工具
JAXP:Java官方提供的XML解析工具,
支持DOM标准,也支持Sax标准
其他的解析工具
JDOM
DOM4J
DOM方式解析XML:
Document
Attr
Element
Text
NodeList
getDocumentElement(); 获得根节点

getChildNodes(); 获得元素节点的所有子节点

item(index) 获得NodeList中指定索引位置的节点

getAttribute("num") 获得指定名字的属性值

getNodeName() 获得节点名称

getTextContent() 获得元素节点中的文本内容

getElementsByTagName("name") 根据标签名获得节点列表
getElementById("1234") 根据标签的ID获得指定的节点
使用DOM方式修改xml数据
TransformerFactory
Transformer
Source
Result
//将内存中的dom对象写到xml文件中 //创建一个写xml的对象工厂 TransformerFactory tff = TransformerFactory.newInstance(); //通过工厂生产一个Transformer对象 Transformer tf = tff.newTransformer(); //要写出的xml数据源 Source xmlSource=new DOMSource(dom); //要写到的目标文件 Result outputTarget=new StreamResult(f ); //将指定的数据源写到指定位置 tf.transform(xmlSource, outputTarget)
怎么通过java中的工具获得XML数据?
XML文件:

Demo类
package XML; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; public class Demo { /** * 使用JAXP工具的DOM方式解析XML * @param args */ public static void main(String args[]) throws Exception{ String path = "C:\\Users\\64138\\Desktop\\aa.xml"; File f = new File(path); //1.创建一个DOM解析器工厂 DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance(); //2.通过工厂生产一个解析器对象 DocumentBuilder builder = factory.newDocumentBuilder(); //3.解析指定的XML文件 Document dom = builder.parse(f); //从Document树上提取数据 // Node node = dom.getFirstChild(); // System.out.println(node); //获得文档的根节点 Element root = dom.getDocumentElement(); System.out.println("根节点:"+root); //由于是一个元素节点,可以获得其所有的儿子节点 NodeList list = root.getChildNodes(); //遍历list for(int i=0;i<list.getLength();i++){ //取得一个子节点 Node node = list.item(i); //如果子节点是一个元素节点,才需要处理 if(node instanceof Element) { //将node强制转换成Element Element stu =(Element)node; //获得stu的属性 String num = stu.getAttribute("num"); System.out.println("num:"+num); //获得stu的儿子节点 NodeList childList = stu.getChildNodes(); for(int j=0;j<childList.getLength();j++){ Node n = childList.item(j); if(n instanceof Element) { Element element = (Element)n; //获得节点名字 String nodeName = element.getNodeName(); //获得节点中包含的文本 String content = element.getTextContent(); System.out.println(nodeName+":"+content); } } } } } }
输出结果:

5.如何使用DOM方式修改xml数据?
package XML; import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.File; public class XmlDemo3 { /** * 使用JAXP工具的DOM方式解析XML * @param args */ public static void main(String args[]) throws Exception{ String path = "C:\\Users\\Administrator\\Desktop\\stus.xml"; File f = new File(path); //1.创建一个DOM解析器工厂 DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance(); //2.通过工厂生产一个解析器对象 DocumentBuilder builder = factory.newDocumentBuilder(); //3.解析指定的XML文件 Document dom = builder.parse(f); //获得根节点 Element root = dom.getDocumentElement(); //创建一个stu标签 Element stu= dom.createElement("stu"); //设置stu标签的num属性 stu.setAttribute("num", "6666"); //将stu节点作为root的子节点 root.appendChild(stu); //给stu加子节点 Element name = dom.createElement("name"); //设置name的文本 name.setTextContent("赵敏"); //将name作为stu的子节点 stu.appendChild(name); //将内存中的dom对象写到xml文件中 //创建一个写xml的对象工厂 TransformerFactory tff = TransformerFactory.newInstance(); //通过工厂生产一个Transformer对象 Transformer tf = tff.newTransformer(); //要写出的xml数据源 Source xmlSource=new DOMSource(dom); //要写到的目标文件 Result outputTarget=new StreamResult(f ); //将指定的数据源写到指定位置 tf.transform(xmlSource, outputTarget); } }
5.如何通过SAX方式获得xml数据?
xml文件

SaxPaserXml类
import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.File; /** * Sax方式解析XML */ public class SaxPaserXml { public static void main(String[] args) throws Exception{ String path = "xml/stus.xml"; File f = new File(path); //1.创建Sax解析器工厂 SAXParserFactory factory =SAXParserFactory.newInstance(); //2.通过工厂生产一个sax解析器对象 SAXParser saxPaser = factory.newSAXParser(); //3.创建事件处理器对象 DefaultHandler handler = new MyHander(); //4.开始解析 saxPaser.parse(f,handler); } }
MyHander类
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.ArrayList; /** * Sax的事件处理器,继承DefaultHandler * 需要重写DefaultHandler的事件处理方法 * 事件处理器中的方法是通过事件触发自动调用的 * */ public class MyHander extends DefaultHandler { //创建一个数组对象 ArrayList<Student> list = new ArrayList<>(); String msg=null; Student stu =null; //开始解析文档 @Override public void startDocument() throws SAXException { System.out.println("startDocument"); } //解析到开始标签,需要处理标签中的属性 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(qName.equals("stu")) { //当开始标签是stu的时候,就需要创建一个学生对象 stu = new Student(); //设置学生对象的num属性 String snum = attributes.getValue("num"); //需要先将字符串的num转换成int类型 int num = Integer.parseInt(snum); stu.setNum(num); } } //解析到文本内容 @Override public void characters(char[] ch, int start, int length) throws SAXException { msg = new String(ch,start,length); } //解析到结束标签 @Override public void endElement(String uri, String localName, String qName) throws SAXException { switch (qName){ case "name": stu.setName(msg); break; case "age": int age = Integer.parseInt(msg); stu.setAge(age); break; case "sex": stu.setSex(msg.trim().charAt(0)); break; case "stu": //如果结束标签是stu,就将学生对象保存到list中 list.add(stu); break; } } //解析文档结束 @Override public void endDocument() throws SAXException { //输出list for(Student stu:list){ System.out.println(stu); } System.out.println("endDocument"); } }
Student类
public class Student { private int num; private String name; private int age; private char sex; public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } @Override public String toString() { return "Student{" + "num=" + num + ", name='" + name + '\'' + ", age=" + age + ", sex=" + sex + '}'; } }
输出结果:


浙公网安备 33010602011771号