1、了解XML
1. XML,即可扩展标记语言(Extensible Markup Language),标准通用标记语言的子集,一种用于标记电子文件使其具有结构性的标记语言。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。它和JSON都是一种数据交换格式。
2、什么是可扩展标记语言?
· 可扩展标记语言是一种很像超文本标记语言的标记语言。
· 它的设计宗旨是传输数据,而不是显示数据。
· 它的标签没有被预定义。您需要自行定义标签。
· 它被设计为具有自我描述性。
· 它是W3C的推荐标准。
3、解析XML文档的五种方式: 五种方法解析XML文档:Dom、SAX、JDOM、dom4j 、degister
准备xml文件
<?xml version="1.0" encoding="UTF-8"?>
<languages cat="it">
<lang id="1">
<name>Java</name>
<ide>Eclipse</ide>
</lang>
<lang id="2">
<name>Swift</name>
<ide>Xcode</ide>
</lang>
<lang id="3">
<name>c#</name>
<ide>Visual Studio</ide>
</lang>
</languages>
4、SAX
SAX介绍
SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。
与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。
当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。
局限性:
1. SAX分析器在对XML文档进行分析时,触发了一系列的事件,由于事件触发本身是有时序性的,因此,SAX提供的是一种顺序访问机制,对于已经分析过的部分,不能再倒回去重新处理。
即,一旦经过了某个元素,我们没有办法返回去再去访问它。
2. SAX分析器只做了一些简单的工作,大部分工作还要由应用程序自己去做。
也就是说,SAX分析器在实现时,只是顺序地检查XML文档中的字节流,判断当前字节是XML语法中的哪一部分、是否符合XML语法,然后再触发相应的事件,而事件处理函数本身则要由应用程序自己来实现。
同DOM分析器相比,SAX分析器缺乏灵活性。
优势:
然而,由于SAX分析器实现简单,对内存要求比较低,(SAX不必将整个XML文档加载到内存当中,因此它占据内存要比DOM小), 因此实现效率比较高。
对于大型的XML文档来说,通常会用SAX而不是DOM。
并且对于那些只需要访问XML文档中的数据而不对文档进行更改的应用程序来说,SAX分析器更为合适。
DefaultHandler类:
4.1 读取xml文件
标签的枚举类如下
package org.wuqinghua.java.xml.sax;
/**
* Created by wuqinghua on 17/7/5.
*/
public enum TagName {
LANGUAGES("languages"),LANG("lang"), NAME("name"), IDE("ide"),NONE("none");
private String tagName;
TagName(String tagName) {
this.tagName = tagName;
}
public String getTagName() {
return tagName;
}
public static TagName transformer(String tagName) {
switch (tagName) {
case "languages":
return LANGUAGES;
case "lang":
return LANG;
case "name":
return NAME;
case "ide":
return IDE;
default:
return NONE;
}
}
}
将lang标签设计为一个对象
package org.wuqinghua.java.xml.sax;
/**
* Created by wuqinghua on 17/7/5.
*/
public class Lang {
private String id;
private String name;
private String ide;
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 getIde() {
return ide;
}
public void setIde(String ide) {
this.ide = ide;
}
@Override
public String toString() {
return "Lang{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", ide='" + ide + '\'' +
'}';
}
}
xml顺序执行的handler
package org.wuqinghua.java.xml.sax;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wuqinghua on 17/7/5.
*/
public class SaxHandler extends DefaultHandler {
private List<Lang> langs = null;
private Lang lang = null;
private boolean isName = false;
private boolean isIde = false;
//文档开始触发
@Override
public void startDocument() throws SAXException {
super.startDocument();
}
//文档结束触发
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
//标签开始触发
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
TagName tagName = TagName.transformer(qName);
switch (tagName) {
case NONE:
break;
case LANGUAGES:
if (langs == null)
langs = new ArrayList<>();
break;
case LANG: //解析lang标签
lang = new Lang();
String id = attributes.getValue("id");
lang.setId(id);
break;
case NAME: //解析name标签
isName = true;
break;
case IDE: //解析ide标签
isIde = true;
break;
}
}
//标签结束触发
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (TagName.transformer(qName).equals(TagName.LANG)) {
langs.add(lang);
}
}
//标签中数据触发
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (isName) {
lang.setName(new String(ch, start, length));
isName = false;
} else if (isIde) {
lang.setIde(new String(ch, start, length));
isIde = false;
}
}
public List<Lang> getLangs() {
return langs;
}
}
读取xml
public void readXML() throws ParserConfigurationException, SAXException, IOException {
//1.获取SAX解析器的工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//2.获取SAX解析器
SAXParser saxParser = factory.newSAXParser();
//3.创建顺序读取xml的处理器
SaxHandler handler = new SaxHandler();
//4.解析xml
saxParser.parse(this.getClass().getClassLoader().getResourceAsStream("xml/languages" +
".xml"),handler);
System.out.println(handler.getLangs());
}
4.2 创建xml文件
public void createXML() throws TransformerConfigurationException, SAXException {
//1.获取SAXTransformerFactory实例
SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
//2.创建TransformerHandler实例
TransformerHandler transformerHandler = factory.newTransformerHandler();
//3.创建Transformer对象
Transformer transformer = transformerHandler.getTransformer();
//4、设置输出的xml属性,encoding为编码,indent是确保输出的xml文件能够自动换行
transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
//5、创建Result对象,将Result对象加载到TransHandler中
//注意:1、这一步必须在Transformer.setOutputProperty()之后,不然设置的xml属性将不生效
// 2、这一步也必须在TransformerHandler.startDocument()之前,不然会报错。
// 分析源码后发现,startDocument()会先判断result是否为空,为空则报错
Result result = new StreamResult("newxml.xml");
transformerHandler.setResult(result);
//6、创建属性Attribute对象
AttributesImpl attr = new AttributesImpl();
//7.开始写文件
transformerHandler.startDocument();
//8.写入根节点
attr.clear();
//设置属性
attr.addAttribute("","","cat","","it");
transformerHandler.startElement("","",TagName.LANGUAGES.getTagName(),attr);
//设置lang节点
attr.clear();
attr.addAttribute("","","id","","1");
transformerHandler.startElement("","",TagName.LANG.getTagName(),attr);
//设置name节点
attr.clear();;
transformerHandler.startElement("","",TagName.NAME.getTagName(),attr);
transformerHandler.characters("java".toCharArray(),0,"java".toCharArray().length);
transformerHandler.endElement("","",TagName.NAME.getTagName());
//设置ide
attr.clear();
transformerHandler.startElement("","",TagName.IDE.getTagName(),attr);
transformerHandler.characters("Eclipse".toCharArray(),0,"Eclipse".toCharArray().length);
transformerHandler.endElement("","",TagName.IDE.getTagName());
transformerHandler.endElement("","",TagName.LANG.getTagName());
transformerHandler.endElement("","",TagName.LANGUAGES.getTagName());
//9.结束
transformerHandler.endDocument();
}