XML解析——DOM解析
XML:可扩展性标记语言,主要用来传输和存储数据,相对于HTML的各种标签规范,XML的标签可以让用户根据语义自己进行定义,适用于web传输。
JSON和XML的区别:
(1).XML定义
扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML使用DTD(document type definition)文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准。
XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。
(2).JSON定义
JSON(JavaScript Object Notation)一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。可在不同平台之间进行数据交换。JSON采用兼容性很高的、完全独立于语言文本格式,同时也具备类似于C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)体系的行为。这些特性使JSON成为理想的数据交换语言。
JSON基于JavaScript Programming Language , Standard ECMA-262 3rd Edition - December 1999 的一个子集。
2.XML和JSON优缺点
(1).XML的优缺点
<1>.XML的优点
A.格式统一,符合标准;
B.容易与其他系统进行远程交互,数据共享比较方便。
<2>.XML的缺点
A.XML文件庞大,文件格式复杂,传输占带宽;
B.服务器端和客户端都需要花费大量代码来解析XML,导致服务器端和客户端代码变得异常复杂且不易维护;
C.客户端不同浏览器之间解析XML的方式不一致,需要重复编写很多代码;
D.服务器端和客户端解析XML花费较多的资源和时间。
(2).JSON的优缺点
<1>.JSON的优点:
A.数据格式比较简单,易于读写,格式都是压缩的,占用带宽小;
B.易于解析,客户端JavaScript可以简单的通过eval()进行JSON数据的读取;
C.支持多种语言,包括ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等服务器端语言,便于服务器端的解析;
D.在PHP世界,已经有PHP-JSON和JSON-PHP出现了,偏于PHP序列化后的程序直接调用,PHP服务器端的对象、数组等能直接生成JSON格式,便于客户端的访问提取;
E.因为JSON格式能直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,且完成任务不变,并且易于维护。
<2>.JSON的缺点
A.没有XML格式这么推广的深入人心和喜用广泛,没有XML那么通用性;
B.JSON格式目前在Web Service中推广还属于初级阶段。
3.XML和JSON的优缺点对比
(1).可读性方面。
JSON和XML的数据可读性基本相同,JSON和XML的可读性可谓不相上下,一边是建议的语法,一边是规范的标签形式,XML可读性较好些。
(2).可扩展性方面。
XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。
(3).编码难度方面。
XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了。
(4).解码难度方面。
XML的解析得考虑子节点父节点,让人头昏眼花,而JSON的解析难度几乎为0。这一点XML输的真是没话说。
(5).流行度方面。
XML已经被业界广泛的使用,而JSON才刚刚开始,但是在Ajax这个特定的领域,未来的发展一定是XML让位于JSON。到时Ajax应该变成Ajaj(Asynchronous Javascript and JSON)了。
(6).解析手段方面。
JSON和XML同样拥有丰富的解析手段。
(7).数据体积方面。
JSON相对于XML来讲,数据的体积小,传递的速度更快些。
(8).数据交互方面。
JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互。
(9).数据描述方面。
JSON对数据的描述性比XML较差。
(10).传输速度方面。
JSON的速度要远远快于XML。
既然有数据的存储,就必然要有数据的读取和解析,解析出来的数据才可以被我们用在web上。在W3C中定义了两种解析XML的两种方式:SAX和DOM
这两种解析方式的程序操作如下:
XML应用程序 《= DOM接口 《= XML分析器 《= XML文档
XML应用程序 《= SAX接口 《= XML分析器 《= XML文档
XML分析器会对XML文档先进行分析,分析结果经过DOM或SAX接口对分析结果进行操作,从而实现间接地对XML文档的访问。
(1)基于DOM的XML解析器
DOM类型的解析器会将XML文档转换成一颗DOM树,即将元素和元素之间的父子关系转化成一棵树和它的枝干,这种方法的好处是可以任意的控制整个XML文档的内容,但是这种方法有缺点,他需要将整个文档解析成一颗DOM树放在内存中,这就极其占用内存,所以当XML文档比较大,结构复杂时不采用这种解析方式,但在结构简单,比较小的XML文档中这种方式还是应用很广泛的。
先定义一个简单的XML文档:
<?xml version="1.0" encoding="GBK"?> <addresslist> <linkman> <name>张三</name> <email>aaa@qq.com</email> </linkman> <linkman> <name>李四</name> <email>bbb@qq.com</email> </linkman> </addresslist>
在DOM解析中有四个核心的操作接口:
(1)document :这个接口就是整个XML文档
这个接口下的常用方法:
No. | 方法 | 类型 | 描述 |
1 | public NodeList getElementsByTagName(String tagname) | 普通 | 根据节点名称取得节点 |
2 | public Element createElement(String tagname) throws DOMException | 普通 | 创建一个制定名称的节点 |
3 | public Text create TextNode(String data) | 普通 | 创建一个文本内容节点 |
4 | Element createElement(String tagName) throws DOMException | 普通 | 创建一个节点元素 |
5 | public Attr createAttribute(String name) throws DOMException | 普通 | 创建一个属性 |
(2)Node:每一个Node接口代表一个DOM树中的一个节点,是十分重要的一个接口
No. | 方法 | 类型 | 描述 |
1 | Node appendChild(Node newChild) throws DOMException | 普通 | 在当前节点下增加一个新节点 |
2 | public NodeList getChildNodes() | 普通 | 取得本节点下的全部子节点 |
3 | public Node getFirstChild() | 普通 | 取得本节点下第一个子节点 |
4 | public Node getLastChild() | 普通 | 取得本节点下最后一个子节点 |
5 | public boolean hasChildNodes() | 普通 | 判断是否还有其他节点 |
6 | public boolean hasAttributes() | 普通 | 判断是否还有其他属性 |
7 | String getNodeValue() throws DOMException | 普通 | 取得节点内容 |
/*throws语句含义:加在方法大括号之前,将方法中没有 try catch 的异常抛出去,交给其他调用该方法的方法 处理,如果其他方法还不处理,可以继续往外throws
详见http://blog.chinaunix.net/uid-26359455-id-3130427.html*/
(3)NodeList:表示一个节点的集合,一般是有顺序关系的一组节点,当文档改变时会直接影响到NodeList集合
No. | 方法 | 类型 | 描述 |
1 | public int getLength() | 普通 | 取得节点的个数 |
2 | public Node item(int index) | 普通 | 根据索引取得节点对象 |
(4)NamedNodeMap:表示一组节点和其唯一名称对应的一一对应关系,主要用于属性节点的表示。
一个程序要进行DOM解析操作,要按照如下步骤进行:
(1)建立DocumentBuilderFactory:DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
(2)建立DocumentBuilder:DocumentBuilder builder = factory.newDcumentBuilder();
(3)建立Document:Document doc = builder.parse("要读取的文件路径");
(4)建立NodeList:NodeList nl = doc.getElementsByTagName("读取节点");
(5)进行XML信息读取。
参考书上的例子:
读取xml文件内容的Java代码:
1 import java.io.File; 2 import java.io.IOException; 3 import javax.xml.parsers.DocumentBuilder; 4 import javax.xml.parsers.DocumentBuilderFactory; 5 import javax.xml.parsers.ParserConfigurationException; 6 import org.w3c.dom.Document; 7 import org.w3c.dom.NodeList; 8 import org.xml.sax.SAXException; 9 public class DOMDemo01 { 10 public static void main(String args[]){ 11 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 12 DocumentBuilder builder = null; 13 try{ //若try语句中的内容出现错误,则会执行catch语句中的代码 14 builder = factory.newDocumentBuilder(); 15 }catch(ParserConfigurationException e){ 16 e.printStackTrace(); //弹出出错位置的栈 17 } 18 Document doc = null; 19 try{ //读取指定路径的XML文件,相当于将所有的xml文档内容读取到内存中,从而将所有的xml文件内容按照节点的定义顺序将其变为一颗内存中的DOM树,供用户解析使用。
doc = builder.parse("D:"+File.separator+"my_workspace"+File.separator+"dsd"+File.separator+"src"+File.separator+"MyXml.xml");
21 }catch(SAXException e){ 22 e.printStackTrace(); 23 }catch24 e.printStackTrace(); 25 } 26 NodeList nl = doc.getElementsByTagName("name"); 27 System.out.println("姓名:"+nl.item(0).getFirstChild().getNodeValue()); 28 } 29 30 }
xml文件内容:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <xml-body> 3 <name>张三</name> 4 </xml-body>
程序运行结果:姓名:张三
(6)用Java程序创建一个XML文件,例程:
1 import java.io.File; 2 import javax.xml.parsers.DocumentBuilder; 3 import javax.xml.parsers.DocumentBuilderFactory; 4 import javax.xml.parsers.ParserConfigurationException; 5 import javax.xml.transform.OutputKeys; 6 import javax.xml.transform.Transformer; 7 import javax.xml.transform.TransformerConfigurationException; 8 import javax.xml.transform.TransformerException; 9 import javax.xml.transform.TransformerFactory; 10 import javax.xml.transform.dom.DOMSource; 11 import javax.xml.transform.stream.StreamResult; 12 import javax.lang.*; 13 import org.w3c.dom.*; 14 import org.w3c.dom.Document; 15 import org.w3c.dom.Element; 16 import org.w3c.dom.NodeList; 17 import org.xml.sax.SAXException; 18 public class DOMDemo01 { 19 public static void main(String args[]){ 20 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //创建一个DocumentBuilderFactory 21 DocumentBuilder builder = null; 22 try{ 23 builder = factory.newDocumentBuilder(); //创建失败 24 }catch(ParserConfigurationException e){ 25 e.printStackTrace(); 26 } 27 Document doc = null; 28 doc=builder.newDocument(); //创建一个Document对象,并让它与builder产生关联 29 Element addresslist=(Element) doc.createElement("addresslist"); //创建子节点addresslist 30 Element linkman=(Element) doc.createElement("linkman"); //创建子节点linkman 31 Element name=doc.createElement("name"); //创建子节点name 32 Element email=doc.createElement("email"); //创建子节点email 33 name.appendChild(doc.createTextNode("李四")); //给子节点name中插入文本内容 34 email.appendChild(doc.createTextNode("22222@qq.com")); //给子节点email中插入文本内容 35 addresslist.appendChild(linkman); //将子节点linkman插入到addresslist中 36 linkman.appendChild(name); //将子节点name插入到linkman中 37 linkman.appendChild(email); //将子节点email插入到linkman中,以上插入语句顺序可变 38 doc.appendChild(addresslist); //所有节点插入到该文档中 39 TransformerFactory tf=TransformerFactory.newInstance(); //创建一个类型为TransformFactory的对象实例 40 Transformer t=null; 41 try{ 42 t=tf.newTransformer(); 43 }catch(TransformerConfigurationException e1){ 44 e1.printStackTrace(); 45 } 46 t.setOutputProperty(OutputKeys.ENCODING, "GBK"); //设置编码格式 47 DOMSource source=new DOMSource(doc); 48 StreamResult result=new StreamResult(new File("d:"+File.separator+"output.xml")); 49 try{ 50 t.transform(source, result); 51 }catch(TransformerException e){ 52 e.printStackTrace(); 53 } 54 } 55 }
运行结果:
可以看到生成了一个XML文件
通过以上代码,可以看出java生成XML文件编码的思想是,先外后里,即先创建子节点,再创建父节点,将子节点插入父节点,再创建文档,将节点内容插入文档,最后再在计算机中申请空间,将整个文档放入。
DocumentBuilderFactory