xml的解析

要处理xml文件,就要先解析他,解析器是这样工作的,他读入一个文件,确认这个文件具有正确的格式,然后将其分解成各种元素,使得程序员能够访问各个元素。

java提供了两种xml解析器:

1 DOM解析器(树形解析器)

2 SAX解析器(流机制解析器)

one by one 让我们先来学习DOM解析器

所谓树形解析器就是把xml文件的各个元素按照树形结构读入内存,如果是大型的xml文件,这对我们的内存也是一个相当大的考验。

<student id="138896"> 
	<name>王五</name>		
	<age>16</age>	
</student>

着是一个简单的xml文件,让我们看看dom解析器读进内存是什么样子的:

好了,我们知道dom解析器是读入xml文件的格式了,我们可以大体上吧xml文件的内容分为下面的对象:

1 文档: Document对象

2 元素: Element对象

3 标签内容 :Text对象

4 属性:Attr对象

好了,那摩我们如何来得到解析器呢?下面的代码将会告诉我们:

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //通过工厂类的newInstance()函数创建DocumentBuilderFactory实例
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); //创建DocumentBuilderFactory实例创建documentBuilder实例
Document document = documentBuilder.parse("src/day.xml"); //获得document对象
Node fElement = document.getDocumentElement();//获得根元素的Element对象
我们可以通过根元素对象来遍历子元素实现xml文件的遍历,代码小施:

public class JaxpTest {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //通过工厂类的newInstance()函数创建DocumentBuilderFactory实例
		DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); //创建DocumentBuilderFactory实例创建documentBuilder实例
		Document document = documentBuilder.parse("src/day.xml"); //获得document对象
		Node fElement = document.getDocumentElement();
		bianli(fElement);
		
	}
	
	public static void bianli(Node node) {
		if(node instanceof Element){  //判断获取的子元素是否是Element对象
			Element element = (Element) node; //若果是我们就进行类型转换
			System.out.print("<" + element.getTagName()); //打印开始标签名称
			NamedNodeMap nNM = element.getAttributes(); //得到元素的属性对象集
			for (int i = 0; i < nNM.getLength(); i++) { //遍历属性对象集并打印属性名和值
				Attr attr = (Attr)nNM.item(i);
				System.out.print(" " + attr.getName() + "=\"" + attr.getValue() + "\"");
			}
			System.out.println(">");
			NodeList nL = element.getChildNodes(); //获取子元素集
			for(int i = 0;i < nL.getLength(); i++) { //遍历子元素
				Node nNode = nL.item(i);
				bianli(nNode);  //递归过程
			}
			System.out.println("</" + element.getTagName() + ">"); //打印结束标签
		}
		
		else if(node instanceof Text) {  //如果得到的子元素是Text对象就对其内容进行输出
			Text t = (Text) node;
			System.out.println(t.getData().trim()); //去除内容体中的空格
		}
	}

}
好了,这就是dom解析器的大致操作,更多详细内容请自己查看API。

那摩问题来了,这如果我们的xml文件相当的大而我们只需要查找里面的一少部分内容,但是这些内容对于一个树形结构来说又太深了,我们总不能一层一层的查找吧,这样的代码量反正我是写不下去。那摩我们想要偷懒就得使用XPath喽!

XPath是用来更好的查询xml标签的,他的具体使用可以参见网页文档,可以是中文的哦!

http://www.zvon.org/xxl/XPathTutorial/General_chi/examples.html
关于xpath的使用大致分这几个过程:
1 构建XPath工厂实例
2 通过XPath工厂构建XPath实例
3 利用实例的evaluate()方法来得到你想要的结果,这是一个重载方法:
详细情况可以参见api,下面是一个XPath使用的小应用:
public class XpathTest {

	public static void main(String[] args) throws Exception {
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();//获取xml文件解析器对象
		DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();//获取文件解析器
		Document doc = documentBuilder.parse("src/day.xml");//得到document对象
		XPathFactory xPathFactory = XPathFactory.newInstance();//得到XPath工厂实例
		XPath xp = xPathFactory.newXPath();//得到XPath实例
		Node node = (Node) xp.evaluate("/class/student"/*XPath表达式*/, doc/*关于xml的四种对象*/,XPathConstants.NODE/*返回值类型*/);//利用XPath实例的evaluate方法来获取这个元素
		if(node instanceof Node) {
			Element element = (Element)node;
			System.out.println(element.getTagName() + " id=\"" + element.getAttribute("id") + "\"");//得到该元素的属性
		}
	}

}
好了我们学了dom解析器,是不是还有一个sax解析器,来吧!没办法硬着头皮学吧!
sax解析器
和使用dom解析器一样我们得得到解析器的一个实例:

首先我们来讲解一下sax解析器的解析原理:



好了,明白了这个原理让我们来编写一个遍历xml文件的代码是不是更加简单!
public class SaxXmlTest {

	public static void main(String[] args) throws Exception {
		SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
		SAXParser saxParser = saxParserFactory.newSAXParser();
		MyDH dh = new MyDH();
		saxParser.parse("src/day.xml", dh);
	}
}

public class MyDH extends DefaultHandler{

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
			System.out.print("<" + qName);
			if(attributes.getLength() != 0) {
				for(int i = 0;i < attributes.getLength();i++) {
					System.out.print(attributes.getQName(i) + "=\"" + attributes.getValue(i) + "\"");
				}
			}
			System.out.println(">");
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println("</" + qName + ">");
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		for (int i = 0; i < length; i++) {
			char c = ch[start + i];
			System.out.print(c);
		}
		System.out.println();
	}
}

但是我们不得不面对一个现实,那就是我们在实际开发中是不使用这两种方式的,但是我们为什么还来学习他们呢,注意我们学的只是他们的原理,其实其他的解析方式,也是根据这两个原理来的,所谓一法通,万法通,我们会了这两个,其他的也就差不多了。
我们在实际开发中使用的较为多的是dom4j,这个解析器我真的不想多说,就给个例子就行了,我们原理都会了,害怕他,开玩笑,万变不离其宗,只是方法名字不同而已。
package com.weijinhao.usedom4j;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Node;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/**
 * 其实使用dom4j和Java自带的解析器在表面操作上没有什么太大的区别,主要是底层实现的原理不相同,dom4j可以说是集成了dom和sax的
 * 优点,即便于增删也便于查找,当然了,dom4j不是JavaSE的部分,所以我们必须得导包。
 * 我们知道要想通过便捷查找就得使用XPath了,但是dom4j默认是不支持XPath的,我们需要导入其jar包。
 * 在dom4j的lib文件夹中,名叫:jaxen-1.1-beta-6.jar
 * 并且使用doucment对象的document.selectSingleNode(arg0);
 * document.selectNodes(arg0);这两个函数来实现查找。
 * 关于XPath的使用方法我们这就不都说了。
 */
public class UseDom4J {

	public static void main(String[] args) throws Exception {
		//simpleUse();
		//useXPath();
	}

	public static void useXPath() throws DocumentException {
		File file = new File("E:/javajichu/usedom4j/one.xml");
		SAXReader saxReader = new SAXReader();//创建解析器
		Document document = saxReader.read(file);//获得doc对象
		List <Node> ls = document.selectNodes("/school/class/student");
		for (Node node : ls) {
			Element e = (Element)node;
			System.out.print(e.getName() + " ");
			List<Node> le = e.attributes();
			for (Node attr : le) {
				System.out.print(attr.getName() + "=" + attr.getStringValue());
			}
			System.out.println();
		}
	}

	public static void simpleUse()
			throws DocumentException, UnsupportedEncodingException, FileNotFoundException, IOException {
		File file = new File("E:/javajichu/usedom4j/one.xml");
		SAXReader saxReader = new SAXReader();//创建解析器
		Document document = saxReader.read(file);//获得doc对象
		
		
		
		Element rootElement = document.getRootElement();
		Element clazz = rootElement.addElement("class");
		clazz.addAttribute("num","计c133");
		Element e1 = clazz.addElement("student");
		e1.addAttribute("name","张三");
		e1.addAttribute("num","138");
		Element e2 = clazz.addElement("student");
		e2.addAttribute("name","李思");
		e2.addAttribute("num","137");
		
		//我们用来获取输出的格式,这样的格式看起来更加友好
		OutputFormat format = OutputFormat.createPrettyPrint();
		XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(file), format);
		xmlWriter.write(document);//保存我们的修改
		xmlWriter.close();
	}

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值