Java操作XML文件(读)

一、概述:

   目前,Java平台上对XML文件的操作主要有4中方式:DOM、SAX、DOM4J以及JDOM,前两种Java平台自带的解析操作方式,后两种是第三方提供的,所以使用的时候需要导入相应的jar包,需要的可以去下载:jar包下载


二、DOM 方式解析

  DOM方式官方提供的方式,非Java平台独有,很多其它平台也可使用此方式,即具有跨平台的特点,它的特点主要是易用性强,遍历简单,但是因为它是一次性将XML文档全部读取到内存中,所以比较吃内存,效率低,当文件很大时,容易发生内存泄漏。主要操作代码如下,注释很详细,就不再做说明:

package com.jamie.xml;

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * DOM方式解析XML文件
 * 
 * @author Jamie
 * 
 */
public class DomTest {

	public void parseXml() {
		// 通过工厂类的newInstance,创建一个DocumentBuilderFactory的对象
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

		try {
			// 获得一个DocumentBuilder对象
			DocumentBuilder db = dbf.newDocumentBuilder();
			// 通过DocumentBuilder的parse方法读取xml文件,得到Document对象
			System.out.println("=======开始解析XML文件======");
			Document doc = db.parse("class.xml");
			// 获取所有person节点的集合
			NodeList personList = doc.getElementsByTagName("person");
			// getLength方法可获得节点的个数
			System.out.println("当前共有 " + personList.getLength() + "个节点");
			// 遍历节点
			for (int i = 0; i < personList.getLength(); i++) {
				System.out.println("=======第" + (i + 1) + "个节点========");

				// 如果知道节点的属性名并只有一个属性时可用下面的方法:
				/*
				 * Element attEl = (Element) personList.item(i);
				 * //getAttribute()方法获取属性值
				 * System.out.println("ID:"+attEl.getAttribute("id"));
				 */

				Node personNode = personList.item(i);
				// 获取当前节点的属性信息,注意返回值是NamedNodeMap
				NamedNodeMap attrs = personNode.getAttributes();
				// 遍历属性信息,getLength方法可获得属性的个数
				for (int j = 0; j < attrs.getLength(); j++) {
					Node attr = attrs.item(j);
					// 获得属性名和属性值
					System.out.println(attr.getNodeName() + "="
							+ attr.getNodeValue());

				}
				// 遍历子节点
				NodeList chilNodes = personNode.getChildNodes();
				// 打印节点数,会发现输出的结果用我们在XML中看到的有差异,因为程序把两个节点间的换行空格也算作了一个节点,一个类型为text的节点
				// 而像<sex></sex>这种属于Element节点
				System.out.println("当前节点下共有:" + chilNodes.getLength() + "个节点");
				for (int j = 0; j < chilNodes.getLength(); j++) {
					Node child = chilNodes.item(j);
					// 区分出text类型的节点以及element类型的节点
					if (child.getNodeType() != Node.TEXT_NODE)
						// 打印输入节点名和对应的值,注意获取值采用的是getTextContent,而不是getNodeValue()
						System.out.println(child.getNodeName() + ":"
								+ child.getTextContent());
				}
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		DomTest dt = new DomTest();
		// 调用DOM解析方法
		dt.parseXml();
	}

}


三、SAX方式解析

      上面说道DOM解析需要一次性将XML文件读到内存中,当文件很大时,会造成效率低下等问题,而SAX解析相比DOM就是一种速度更快更有效的方式,因为它采用的是一行行读取XML文件的方式,但是也正是这样的特性导致SAX的操作会比较复杂,基于事件驱动方式,灵活性也比较低,具体操作代码如下(SAX解析时,需要一个DefaultHandler类,所以代码分两块):

SaxTest类:

package com.jamie.xml;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

import com.jamie.handler.SaxParserHandler;

/**
 * SAX方式解析XML文件
 * 
 * @author Jamie
 * 
 */
public class SaxTest {
	public void saxParse() {
		// 通过SAXParserFactory类的newInstance()方法获得一个SAXParserFactory对象
		SAXParserFactory saf = SAXParserFactory.newInstance();
		try {
			// 创建一个SAXParser对象
			SAXParser parser = saf.newSAXParser();
			// SAX解析XML 时需要一个类继承DefaultHandler类成为Handler类,来进行具体的解析操作
			SaxParserHandler handler = new SaxParserHandler();
			parser.parse("class.xml", handler);

		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		SaxTest st = new SaxTest();
		st.saxParse();
	}

}

SaxParserHandler类:

package com.jamie.handler;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SaxParserHandler extends DefaultHandler {
	int index = 0;

	// 开始遍历xml文档
	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		System.out.println("==开始解析===");
	}

	// 结束遍历xml文档
	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.endDocument();
		System.out.println("==结束解析===");
	}

	// 遍历开始标签
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		super.startElement(uri, localName, qName, attributes);
		// 开始解析person 标签,标签名区分大小写
		if (qName.equals("person")) {
			index++;
			System.out.println("======开始遍历第" + index + "个人======");
			// 知道属性名及个数时:
			// String id = attributes.getValue("id");
			// System.out.println("属性值为:" + id);
			// 不知道属性名及个数时:

			int length = attributes.getLength();
			for (int i = 0; i < length; i++) {
				String id = attributes.getValue(i);
				String name = attributes.getQName(i);
				System.out.println("属性名为:" + name + ";属性值为:" + id);
			}

		} else {
			if (!qName.equals("class") || !qName.equals("person"))
				System.out.print("节点名是:" + qName);
		}
	}

	// 遍历结束标签
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		// 判断是否结束person标签
		if (qName.equals("person")) {
			System.out.println("======结束遍历第" + index + "个人======");
		}
	}

	// 获取节点的内容char[] ch是文档里的所有节点内容
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		super.characters(ch, start, length);
		String value = new String(ch, start, length);
		if (!value.trim().equals("")) {
			System.out.println("节点值:" + value);
		}

	}

}

四:JDOM方式解析

        JDOM是一种简化的API,使用具体类而不是接口,这样方便使用,但是同时灵活性比较低,API大量使用了Collections类,如果你对集合类熟悉,使用JDOM就会很容易,具体操作代码如下:

package com.jamie.xml;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

/**
 * JDOM方式解析XML文件
 * 
 * @author JamieXu
 * 
 */

public class JDomTest {
	public static void main(String[] args) {
		// 使用JDOM方式解析,首先需要创建一个SAXBuilder对象
		SAXBuilder saxb = new SAXBuilder();
		// 创建一个输入流,将XML文件读取到输入流中
		InputStream is;
		try {
			is = new FileInputStream("class.xml");
			//用InputStreamReader包装一下InputStream,将字节流转换为字符流,指定字符集可以解决解析时出现的乱码
			InputStreamReader isr= new InputStreamReader(is, "UTF-8");
			// 通过SAXBuilder的build方法,将输入流读取,返回的是Document对象
			Document doc = saxb.build(isr);
			// 获取XML文件的根节点
			Element rootElement = doc.getRootElement();
			// 获取根节点下的所有子节点,返回的一个Element的集合
			List<Element> personList = rootElement.getChildren();
			for (Element person : personList) {
				System.out.println("=====开始解析第" + (personList.indexOf(person) + 1)
						+ "个人=====");
				// 解析属性
				List<Attribute> attrList = person.getAttributes();
				for (Attribute attr : attrList) {
					String name = attr.getName();
					String value = attr.getValue();
					System.out.println("属性名:" + name + " 属性值:" + value);
				}
				
				// 遍历获取解析下一级的所有子节点,即person下的子节点
				List<Element> personChildList = person.getChildren();
				for (Element personChild : personChildList) {
					for (Attribute attr : attrList) {
						String name = personChild.getName();
						String value = personChild.getValue();
						System.out.println("节点名:" + name + " 节点值:" + value);
					}
				}
				System.out.println("=====结束解析第" + (personList.indexOf(person) + 1)
						+ "个人=====");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

五:DOM4J方式解析

           DOM4J使用接口和抽象基本类方法,是一个优秀的Java XML API,是JDOM的一种智能分支,合并了许多超出基本XML文档表示的功能,具有性能优异、功能强大和极其易使用的特点,因此是使用非常广泛的一中解析XML文件的方式。具体操作代码如下:

package com.jamie.xml;

import java.io.File;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * Dom4jTest方式解析XML文件
 * 
 * @author JamieXu
 * 
 */
public class Dom4jTest {
	public static void main(String[] args) {
		// 创建SAXReader对象
		SAXReader sar = new SAXReader();
		try {
			// 通过SAXReader对象的read方法加载xml文件,返回Document对象
			Document doc = sar.read(new File("class.xml"));
			// 获取根节点及其迭代器
			Element rootElement = doc.getRootElement();
			Iterator eIterator = rootElement.elementIterator();
			// 遍历迭代器,获取根节点中的信息
			while (eIterator.hasNext()) {
				Element person = (Element) eIterator.next();
				System.out.println("====开始解析某个" + person.getName() + "====");
				List<Attribute> attrList = person.attributes();
				for (Attribute attribute : attrList) {
					System.out.println("属性名:" + attribute.getName() + " 属性值:"
							+ attribute.getValue());
				}
				// 获取Person节点的子节点迭代器并遍历节点
				Iterator childIterator = person.elementIterator();
				while (childIterator.hasNext()) {
					Element child = (Element) childIterator.next();
					System.out.println("节点名:" + child.getName() + " 节点值:"
							+ child.getText());
				}
				System.out.println("====结束解析====");
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
}

最后附上测试读取用的XML例子:

<?xml version="1.0" encoding="UTF-8"?>
<class>
<person id="1">
	<name>小明</name>
	<age>13</age>
	<sex>男</sex>
	<hobby>篮球</hobby>
</person>
<person id="2">
	<name>小红</name>
	<age>12</age>
	<sex>女</sex>
</person>
</class>

以上代码都是自己边看边学边敲出来,如果有什么问题,欢迎大家指出,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值