XML从认识到实战

1 篇文章 0 订阅
认识XML
XML是一种标记性语言,使用XML可以方便的实现数据交换、系统配置、内容管理等功能。XML与HTML类似,最大不同是HTML中的元素都是固定的,且以显示为主,而XML语言中的标记都是由用户自定义的,主要以数据保存为主。
XML和HTML的比较:
NO.比较内容HTMLXML
1可扩展性不具有扩展性是无标记语言,可定义新的标记语言
2侧重点侧重于如何显示信息侧重于如何结构化地描述信息
3语法要求不要求标记的嵌套、配对等,不要求标记之间具有一定的顺序严格要求嵌套、配对,遵循统一的循序结构要求
4可读性及可维护性难于阅读、维护结构清晰、便于维护、阅读
5数据和显示的关系内容描述与显示方式融合在一起内容描述与显示方式相分离
6保值性不具有保值性具有保值性
下面给出XML文件的简单范例:
<?xml version="1.0" encoding="GBK"?>
<addresslist>
	<linkman>
		<name>小王</name>
		<email>xaiowang@163.com</email>
	</linkman>
	<linkman>
		<name>阿樱</name>
		<email>aying@163.com</email>
	</linkman>
</addresslist>
由上例可见XML文件由前导区和数据区两部分组成。前导区包括下面三个属性( 顺序不能错):
  • version: 表示使用的XML版本,现在是1.0。
  • encoding: 页面中使用的文字编码,如果有中文,一般指定GBK编码格式。
  • standalone: 此XML文件是否是独立运行,如果需要进行显示可以使用CSS或XSL控制。

XML中使用的是自定义的元素,同时也可以定义属性,属性的内容必须使用“”括起来。 注意:如果不需要显示可以使用属性,需要显示出来则使用元素。

XML的解析
本文仅着重介绍XML作为数据存储应用,因此对于显示部分不做过多介绍。了解了XML的基本介绍后,下面介绍如果解析XML文件和如何生成自定义的XML文件。
W3C定义了SAX和DOM两种解析方式,如下图所示:
SAX可以快速扫描一个大型的XML文档,当它找到查询标准时就会立即停止,然后再处理之。DOM是把XML全部加载到内存中建立一棵树之后再进行处理。所以DOM不适合处理大型的XML。
同理,DOM的弱项就是SAX的强项,SAX不必把全部的xml都加载到内存中。但是SAX的缺点也很明显,它只能对文件顺序解析一遍,不支持对文件的随意存取。SAX也仅仅能够读取文件的内容,并不能修改内容。DOM可以随意修改文件树,从而修改了xml文件。
SAX解析器和DOM解析器的区别
No.区别SAXDOM
1操作依序读入文件并产生相应的事件,可以处理任何大小的XML文件在内存中建立文件树,不适于处理大型的XML文件
2访问限制只能对文件按顺序剖析一遍,不支持对文件的随意存取可以随意存取文件树的任何部分,没有次数限制
3修改只能读取XML文件内容,而不能修改可以随意修改文件树,从而修改了XML文件
4复杂度开发商比较复杂,需要自己来制作事件处理器易于理解,易于开发
5对象模型对工作人员更灵活,可以用SAX建立自己的XML对象模型已经在DOM基础之上建立文件树
在DOM解析中有以下4个核心的操作接口。
  • Document: 代表整个XML文档,表示整棵DOM树的根,提供了对文档中的数据进行访问和操作的入口。
  • Node: 代表DOM树中的一个节点。
  • NodeList: 表示一个节点的集合,用于表示有顺序关系的一组节点。  
  • NamedNodeMap: 表示一组节点和其唯一名称对应的一一对应关系。
除以上4个核心接口外,如果一个程序需要进行DOM解析读操作,则需要按照如下步骤进行:

下面解析上面提到的xml文件,代码如下:
	public static void main(String args[]) throws Exception {
		// 取得DocumentBuilderFactory类的对象
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance() ;
		// 取得DocumentBuilder类的对象
		DocumentBuilder build = factory.newDocumentBuilder();
		Document doc = null;
		try {
			doc = build.parse(new File("D:" + File.separator + "dom_parse.xml")) ;
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 得到所有的linkman节点
		NodeList nl = doc.getElementsByTagName("linkman") ;
		for(int x=0;x<nl.getLength();x++){
			Element e = (Element) nl.item(x) ;	// 取出每一个元素
			System.out.println("姓名:" + e.getElementsByTagName("name").item(0).getFirstChild().getNodeValue()) ;
			System.out.println("邮箱:" + e.getElementsByTagName("email").item(0).getFirstChild().getNodeValue()) ;
		}
	}

解析结果:

生成XML文件
生成XML文件到硬盘上,需要使用TransformerFactory、Transformer、DOMSource和StreamResult四个类完成。StreamResult类的主要功能时指定要使用的输出流对象,最后通过Transformer类完成内容的输出。
建立完SAX解析器之后,还需要建立SAXParserFactory和SAXParser两个类,可以通过SAXParserFactory的newSAXParser()方法创建SAXParser对象,之后通过SAXParser的parse()方法指定要解析的XML文件和制定的SAX解析器。

代码如下:
	public static void main(String args[]) throws Exception {
		
		// 取得DocumentBuilderFactory类的对象
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance() ;
		// 取得DocumentBuilder类的对象
		DocumentBuilder build = factory.newDocumentBuilder()  ;
		Document doc = build.newDocument() ;	// 创建一个新的XML文档
		
		Element addresslist = doc.createElement("addresslist") ;
		
		Element linkman = doc.createElement("linkman") ;
		Element name = doc.createElement("name") ;
		name.setAttribute("index", "1");		//设置属性
		Element email = doc.createElement("email") ;
		// 设置节点内容
		name.appendChild(doc.createTextNode("小丽")) ;
		email.appendChild(doc.createTextNode("xiaoli@163.com")) ;
		// 该设置各个节点的关系
		linkman.appendChild(name) ;	// name是linkeman的子节点
		linkman.appendChild(email) ;	// email是linkman的子节点
		addresslist.appendChild(linkman) ;
		doc.appendChild(addresslist) ;
		
		TransformerFactory tf = TransformerFactory.newInstance() ;
		Transformer t = tf.newTransformer() ;
		t.setOutputProperty(OutputKeys.ENCODING, "GBK")  ;	// 处理中文的
		DOMSource source = new DOMSource(doc) ;	// 准备输出文档
		StreamResult result = new StreamResult(new File("d:"+File.separator+"output.xml")) ;
		t.transform(source,result) ;
		
	}


生成的文件:

SAX(Simple APIs for XML)解析
SAX采用的是一种循序的模式进行访问,是一种快速读取XML数据的方式。当使用SAX解析器进行操作时会触发一系列的事件,当扫描到文档(Document)开始与结束、元素(Element)开始与结束时都会调用相关的处理方法,并由这些操作方法做出相应的操作,直至整个文档扫描结束。

使用SAX解析,首先应该编写一个SAX解析器,定义一个类,并使该类继承自DefaultHandler类,同时覆写上表列出的方法即可。
SAX解析器代码( 注意使用的包,否则可能出错):
    package com.xml;
	import org.xml.sax.Attributes;
	import org.xml.sax.SAXException;
	import org.xml.sax.helpers.DefaultHandler;

	public class SimpleSAX extends DefaultHandler{

	@Override
	public void startDocument() throws SAXException {

		System.out.println("<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\"?>");
	}
	
	@Override
	public void endDocument() throws SAXException {
		System.out.println("\n 文档读取结束");
	}

	
	@Override
	public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {

		System.out.print("<"+name);
		if (attributes!=null) {
			for(int i=0;i<attributes.getLength();i++){
				System.out.print(" "+ attributes.getQName(i)+"="+"\""+attributes.getValue(i)+"\"");
			}
		}
		System.out.print(">");
	}
	
	@Override
	public void characters(char[] ch, int start, int end) throws SAXException {

		System.out.print(new String(ch,start,end));
	}
	
	@Override
	public void endElement(String uri, String localName, String name) throws SAXException {

		System.out.println("</"+name+">");
	}
	
}


使用SAX解析器:
package com.xml;

import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;

public class XMLtest {

	public static void main(String args[]) throws Exception {
		SAXParserFactory factory = SAXParserFactory.newInstance();
		SAXParser parser = factory.newSAXParser();
		String path = "d:"+File.separator+"qoutput.xml";
		
		try {
			parser.parse(path, new SimpleSAX());
		} catch (Exception e) {	
			e.printStackTrace();
		}
	}

}


解析的XML文件:
<?xml version="1.0" encoding="GBK" standalone="no"?>
<addresslist>
	<linkman>
		<name index="1">小丽</name>
		<email>xiaoli@163.com</email>
	</linkman>
</addresslist>


解析结果:













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值