XML技术
介绍
XML(EXtensible Markup Language)指可扩展标记语言,XML的设计宗旨是传输数据(具有自描述性)而非显示数据。
但是目前人们更多的是使用XML做配置文件而非作为传输数据的载体,业界更多的是使用JSON格式字符串来做载体。
XML技术其实很简单,尤其对于java程序开发人员而言XML技术非常重要XML也算是一个比较悲情的技术,
XML设计之初并不是主要为了作配置文件而设计的,然而目前XML最主要的用途就是作配置文件和数据传输格式。
XML解析
学习XML技术很重要的一点就是解析XML文件
解析XML两种方式
官方的DOM标准解析:其实学习DOM标准接口并不仅仅有助于解析XML,学好DOM也是有助于之后学习JavaScript的。
民间的SAX流解析:基于流来解析XML文件
两种解析方式区别
备注:DOM解析需要将整个XML文件加载到内存中,然后将其虚拟成一棵DOM树,对于比较大的文件来说,解析效率就比较低了。
而SAX是基于流(事件模型)来解析的,它不需要将XML文件都载入到内存然后才能开始解析,它可以载入一部分解析一部分。
DOM解析XML文件
DOM解析XML文件顾名思义就是将XML文件看作是DOM树来对待,所以DOM解析XML的关键就是获得文档对象(Document)。
我觉得DOM模型比XML解析技术本身更有意义,因为DOM模型是w3c抽象出来的标准接口。
要学好DOM第一步就是理解文档对象模型,在DOM定义的标准接口中,将XML中的所有元素都看作是节点Node(),注意Element也是继承Node节点的。

几种重要的元素(节点)类型
//元素节点
ELEMENT_NODE = 1;
//属性节点
ATTRIBUTE_NODE = 2;
//文本节点
TEXT_NODE = 3;
//CDATA节点
CDATA_SECTION_NODE = 4;
//注释节点
COMMENT_NODE = 8;
//文档节点
DOCUMENT_NODE = 9;
Node和Element类
w3c定义的DOM模型,将XML所有的元素都当作节点看待,Node表示节点,Element表示元素继承Node节点。所以它们都是节点。
备注:查看源码看Node节点和Element里面定义了哪些重要方法
掌握Node节点和Element元素非常重要。
获得文档对象Document
//获得XML文件的输入流
InputStream inputStream = new FileInputStream(new File("e:/persons.xml"));
// 创建文档构造器工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
// 创建文档构造器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
// 获得文档对象
Document document = documentBuilder.parse(inputStream);
//获得根节点
Element root=document.getDocumentElement();
通过递归获得某个节点下所有的文本节点对应的内容
/**
* 通过递归Node节点来获得该Node节点下所有的文本节点内容
*
* @param node
*/
private static void getTextNodeValue(Node node) {
if (node == null) {
return;
}
NodeList nodeList = node.getChildNodes();
if (nodeList.getLength() > 1) {
for (int i = 0; i < nodeList.getLength(); i++) {
Node temNode = nodeList.item(i);
if (temNode.getNodeType() == Node.ELEMENT_NODE) {
getTextNodeValue(temNode);
}
}
}
if (node.getNodeType() == Node.ELEMENT_NODE && node.getChildNodes().getLength() == 1) {
System.out.println(node.getNodeName() + ":" + node.getFirstChild().getNodeValue());
}
}
SAX解析XML
相比使用DOM接口来解析XML我觉得SAX并没有DOM重要,因为SAX是为了解决当当个XML文件比较大的时候,DOM解析效率就会降低内存消耗也比较大,因为DOM解析式需要将整个XML文件都载入到内存中解析的。SAX解析可以说是一种新的思想方式来解决了这个问题,基于事件模型来解析XML文件。遇到开始标签就开始解析,直到遇到闭合标签就解析完一个元素了。
获取SAXParser解析对象
// 创建一个解析XML的工厂对象
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
// 创建一个解析XML的对象
SAXParser parser = parserFactory.newSAXParser();
自定义事件处理器
通常我们自定义事件处理器来解析特定的XML文件,通常我们都是自定义一个类使其继承DefaultHandler然后覆盖里面的一些方法完成我们自己想要的逻辑。
自定义事件处理器代码参考
/**
*
* 基于SAX解析XML文件,根据某个节点标签获取该节点下的所有子元素内容(只能拿到一级元素)。
*
*
* @author xuyi3
* @2016年7月20日 @下午1:37:48
* @PersonHandler
* @功能说明:<br>
* @春风十里不如你
* @备注
*/
public class PersonHandler extends DefaultHandler {
// 存储正在解析的元素的数据
private Map<String, String> map = null;
// 存储所有解析的元素的数据
private List<Map<String, String>> list = null;
// 正在解析的元素的名字
private String currentTag = null;
// 正在解析的元素的元素值
private String currentValue = null;
// 开始解析的元素
private String nodeName = null;
public PersonHandler() {
}
public PersonHandler(String nodeName) {
this.nodeName = nodeName;
}
public List<Map<String, String>> getList() {
return list;
}
@Override
public void startDocument() throws SAXException {
list = new ArrayList<Map<String, String>>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (nodeName.equals(qName)) {
map = new HashMap<String, String>();
}
if (attributes != null && map != null) {
for (int i = 0; i < attributes.getLength(); i++) {
String key = attributes.getQName(i);
String value = attributes.getValue(i);
map.put(key, value);
}
}
currentTag = qName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (currentTag != null && map != null) {
currentValue = new String(ch, start, length);
if (currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")) {
map.put(currentTag, currentValue);
}
}
currentTag = null;
currentValue = null;
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// 解析完该元素之后,将map加入到List集合中,然后清空map解析下一个元素。
if (nodeName.equals(qName)) {
list.add(map);
System.out.println("===" + list);
map = null;
}
}
@Override
public void endDocument() throws SAXException {
}
}
基于JDOM解析XML
TODO ...
基于DOM4J解析XML
TODO ...
基于Xstream映射XML to JavaBean
总结
XML技术并不难,但是却是比较重要的一项基本必备技术。其实现在解析xml的组件有很多,个人日常开发比较喜欢Xstream来将xml映射成java对象来处理。