dom4j,xpath,sax,DOM解析xml文件(基础)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhou920786312/article/details/82714459

基础

XML解析器有二类,分别是DOM和SAX。

DOM

DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。

很方便对文档进行遍历 对文档curd也特别方便 xml文档比较大的时候,dom解析占用的内存也会比较大,浪费系统资源。所以dom解析这种方式不适合解析大的xml文档。

SAX

解析文件速度快,占用资源(内存)少。 sax解析只适合读取文档数据,不适合对文档进行增删改。


1 DOM一次性将整个XML文件读到内存,形成一个倒状的树形结构
2 SAX多次将整个XML文件读到内存

SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。


3 Document对象代表XML文件在内存中的映像 


4)dom4j常用的API如下:


    SAXReader saxReader = new SAXReader(); SAXReader是dom4j的核心类
    Document document = saxReader.read("*.xml")
    Document.getRootElement()
    Element.getName()
    Element.elements():取得该元素下的所有直接子元素
      Element.elementText():从一个元素导航到另一个元素且取出该元素的文本
    Element.element("车牌")    :从一个元素导航到另一个元素
    Element.attributeValue("出产时间"):取得一个元素对应的属性
    Element.addElement("单价").setText("40"):添加新元素,同时设置该元素文本的值
    OutputFormat format = OutputFormat.createPrettyPrint():使用缩格形式写XML文件
    XMLWriter xmlWriter = new XMLWriter(os,format):构造XML写入器
    xmlWriter.write(document):将内存中的document对象写入硬盘
    firstCarElement.remove(firstCarPriceElement):从直接父元素删除直接子元素
    //firstCarPriceElement.getParent().remove(firstCarPriceElement):从直接父元素删除直接子元素

5 基于dom4j的xpath技术


 能够在xml文件中,快速定位需要元素,无需从根元素一个一个的导航到需要的子元素
    Document.selectNodes():取得所有符合xpath格式的元素
    Document.selectSingleNode():取得所有符合xpath格式的元素的第一个元素
    Node类型是Element/Text/Attribute/Document/...类型的父接口

 

6练手

 

dom4j解析文件

<?xml version="1.0" encoding="UTF-8"?>
<车辆清单> 
  <汽车> 
    <车牌 出产时间="2010年">奥迪</车牌>  
    <产地>北京</产地>  
    <单价>30</单价> 
  </汽车>  
  <汽车> 
    <车牌 出产时间="2011年">本田</车牌>  
    <产地>广州</产地>  
    <单价>60</单价> 
  </汽车> 
</车辆清单>

代码



import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;

//使用dom4j操作xml文件的cud
public class Demo2 {

	@Test
	public void showXml() throws Exception {
		// 创建dom4j解析器
		SAXReader saxReader = new SAXReader();
		// 加载需要解析的xml文件
		Document document = saxReader.read(new File("src/cn/feizhou/xml/dom4j/car.xml"));
		// 取得根元素
		Element rootElement = document.getRootElement();
		// 显示根元素的名称
		System.out.println(rootElement.getName());
		// 取得根元素下的子元素
		List<Element> elementList = rootElement.elements();
		System.out.println("共有" + elementList.size() + "辆车");
		for (Element e : elementList) {
			System.out.println("车牌:" + e.elementText("车牌"));
			System.out.println("产地:" + e.elementText("产地"));
			System.out.println("出产时间:" + e.element("车牌").attributeValue("出产时间"));
			System.out.println("------------------------------");
		}
	}

	@Test
	/**
	 * 添加元素
	 * 
	 * @throws Exception
	 */
	public void create() throws Exception {
		Document document = getDocument();
		Element rootElement = document.getRootElement();
		// 取得第一辆汽车
		Element firstCarElement = (Element) rootElement.elements().get(0);
		// 添加新元素"单价",并设置文本为30
		firstCarElement.addElement("单价").setText("40");
		// 将内存中的xml文件写到硬盘中
		write2xml(document, "src/cn/feizhou/xml/dom4j/car.xml");
	}

	@Test
	/**
	 * 修改元素
	 * 
	 * @throws Exception
	 */
	public void update() throws Exception {
		Document document = getDocument();
		Element rootElement = document.getRootElement();
		Element firstCarElement = (Element) rootElement.elements().get(0);
		firstCarElement.element("单价").setText("60");
		write2xml(document, "src/cn/feizhou/xml/dom4j/car.xml");
	}

	@Test
	/**
	 * 删除元素
	 * 
	 * @throws Exception
	 */
	public void delete() throws Exception {
		Document document = getDocument();
		Element rootElement = document.getRootElement();
		Element firstCarElement = (Element) rootElement.elements().get(0);
		Element firstCarPriceElement = firstCarElement.element("单价");
		firstCarElement.remove(firstCarPriceElement);
		// firstCarPriceElement.getParent().remove(firstCarPriceElement);
		write2xml(document, "src/cn/feizhou/xml/dom4j/car.xml");
	}

	/**
	 * 字符串转xml
	 * 
	 * @throws Exception
	 */
	@Test
	public void String2XML() throws Exception {
		String text = "<root><res>这是根元素</res></root>";
		Document document = DocumentHelper.parseText(text);
		write2xml(document, "src/cn/feizhou/xml/dom4j/string2xml.xml");
	}

	/**
	 * xml转字符串
	 * 
	 * @throws Exception
	 */
	@Test
	public void XML2String() throws Exception {
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File("src/cn/feizhou/xml/dom4j/car.xml"));
		Element rootElement = document.getRootElement();
		Element firstCarElement = (Element) rootElement.elements().get(0);

		String xml = firstCarElement.asXML();
		System.out.println("xml转字符:" + xml);
	}

	/**
	 * 指定插入次序,默认插入到最后
	 * 
	 * @throws Exception
	 */
	@Test
	public void insertElement() throws Exception {
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File("src/cn/feizhou/xml/dom4j/car.xml"));
		List<Element> elementList = document.getRootElement().elements();
		Element newCarElement = DocumentHelper.createElement("汽车");
		newCarElement.setText("这是我的汽车");
		elementList.add(1, newCarElement);

		write2xml(document, "src/cn/feizhou/xml/dom4j/car.xml");
	}

	/**
	 * 创建空XML
	 * 
	 * @throws Exception
	 */
	@Test
	public void createXML() throws Exception {

		Document document = DocumentHelper.createDocument();
		document.addElement("root").setText("这是根元素");
		write2xml(document, "src/cn/feizhou/xml/dom4j/empty.xml");

	}

	/**
	 * 将Document写入到xml中
	 * 
	 * @param document
	 * @throws Exception
	 */
	private void write2xml(Document document, String xmlPath) throws Exception {
		// 将Document写入到xml中
		// 格式:非紧密,内容多行显示,方便阅读
		OutputFormat format = OutputFormat.createPrettyPrint();
		// 格式:紧密,内容一行显示
		// OutputFormat format = OutputFormat.createCompactFormat()
		OutputStream os = new FileOutputStream(xmlPath);
		XMLWriter xmlWriter = new XMLWriter(os, format);
		xmlWriter.write(document);
		xmlWriter.close();
	}

	/**
	 * 读取xml,并转化为document
	 * 
	 * @return
	 * @throws Exception
	 */
	private Document getDocument() throws Exception {
		// 创建dom4j解析器
		SAXReader saxReader = new SAXReader();
		// 加载需要解析的xml文件
		Document document = saxReader.read(new File("src/cn/feizhou/xml/dom4j/car.xml"));
		return document;
	}
}

xpath读取xml

//使用xpath技术取得xml文件中任意级别下的内容
public class Demo1 {
	public static void main(String[] args) throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/cn/feizhou/xml/xpath/car.xml"));
		String xpath = "//单价";
		Element element = (Element) document.selectSingleNode(xpath);
		System.out.println("第一辆汽车的单价是:" + element.getText());
		//List<Element> elementList = document.selectNodes(xpath);
		//System.out.println("第二辆汽车的单价是:" + elementList.get(1).getText());
	}
}

结果:第一辆汽车的单价是:30

sax解析器解析xml文件


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

//使用sax解析器解析xml文件
public class Demo1 {
	public static void main(String[] args) throws Exception {
		//创建SAX解析器工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//创建SAX解析器
		SAXParser saxParser = factory.newSAXParser();
		//加载xml文件
		saxParser.parse(
				new File("src/cn/feizhou/xml/sax/car.xml"),
				new MyHandler());
	}
}
//自定义SAX处理器
class MyHandler extends DefaultHandler{
	private long begin;
	public void startDocument(){
		System.out.println("解析XML文件开始");
		begin = System.currentTimeMillis();
	} 
	public void endDocument() {
		System.out.println("解析XML文件结束");
		long end = System.currentTimeMillis();
		System.out.println("解析XML共用" + (end-begin) + "毫秒");
	}
	public void startElement(
			String uri, 
			String localName, 
			String qName, 
			Attributes attributes){
		//元素名称
		System.out.println("<"+qName+">");
		//属性数量
		System.out.println("有"+attributes.getLength()+"个属性");
		//属性值
		System.out.println(attributes.getValue("出产时间"));
	} 
	public void endElement(
			String uri, 
			String localName, 
			String qName){
		System.out.println("</"+qName+">");
	} 
	public void characters(
			char[] ch, 
			int start, 
			int length){
		//元素值
		String content = new String(ch,start,length);
		if(content.trim().length()>0){
			System.out.println(content);
		}
	} 
}




结果


解析XML文件开始
<车辆清单>
有0个属性
null
<汽车>
有0个属性
null
<车牌>
有1个属性
2011年
奥迪
</车牌>
<产地>
有0个属性
null
北京
</产地>
<单价>
有0个属性
null
30
</单价>
</汽车>
</车辆清单>
解析XML文件结束
解析XML共用2毫秒








  

上面引用的包

dom4j-1.6.1.jar

jaxen-1.1-beta-6.jar

使用DOM解析器解析XML文件

1 理解dom解析器机制
  1)dom解析和dom4j原理一致
  2)Node是所有元素的父接口
  3)常用的API:
	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();取得DOM解析器工厂
	DocumentBuilder domParser = factory.newDocumentBuilder();取得DOM解析器
	domParser.parse(*.xml)加载需要解析的XML文件
	Document.getDocumentElement()取得XML文件的根元素/节点
	Element.getNodeName():取得根元素
	Element.getElementsByTagName("汽车")取得"汽车"元素的集合
	NodeList.item(i)取得第N个元素,从0开始
	Element.getTextContent():取得元素的文本内容
	Element.getAttributes().getNamedItem("出产时间").getTextContent():取得元素中某属性的值
	document.createElement("汽车");创建新元素
	Element.setTextContent("我的汽车");设置元素的内容
	Element.appendChild(newCarElement);在尾部添加元素
	Element.insertBefore(newCarElement,
			     rootElement.getElementsByTagName("汽车").item(1));在指定的元素前添加元素
	TransformerFactory tf = TransformerFactory.newInstance();创建输出工厂
	Transformer transformer = tf.newTransformer();创建输出对象
	Source source = new DOMSource(document);创建内存的document对象		
	Result result = new StreamResult(new File("XXX/car.xml"));指定输出的目标地点
	transformer.transform(source,result);将document对象输出到xml文件中
        Element.setTextContent("深圳");更新元素的内容
	Element.removeChild(secondCarElement);在父元素基础上删除直接子元素
   4)dom解析器会将空白字符当作有效元素对待 
   5)要让dom解析器将空白字符忽略,必须满足二条件
	a)对XML文件必须写一个DTD约束
	b)factory.setIgnoringElementContentWhitespace(true);
   6)dom类解析器和sax类解析器
	a)dom是一次性加载到内容,形成document对象,人工导航,适合curd
	b)sax是分次性加载到内容,sax解析器导航,但程序员需要编写sax处理器,必须扩展DefaultHandler类


import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Demo2 {
	
	
	 
 
	@Test
	/**
	 * 显示
	 * @return
	 */
		public void showElements() throws Exception{
			Document document = getDocument();
			Element rootElement  = document.getDocumentElement();
			//根元素
			System.out.println("根元素为:"+rootElement.getNodeName());
			//获取标签名为汽车的所有元素
			NodeList nodeList = rootElement.getElementsByTagName("汽车");
			System.out.println("共有:" + nodeList.getLength()+"辆汽车");
			System.out.println("+++++++第一辆汽车的信息+++++++++");
			for(int i=0;i<nodeList.getLength();i++){
				Element element = (Element) nodeList.item(i);
				String band = element.getElementsByTagName("车牌").item(0).getTextContent();
				String place = element.getElementsByTagName("产地").item(0).getTextContent();
				String price = element.getElementsByTagName("单价").item(0).getTextContent();
				String time = element.getElementsByTagName("车牌").item(0).getAttributes().getNamedItem("出产时间").getTextContent();		
				System.out.println("车牌:" + band);
				System.out.println("产地:" + place);
				System.out.println("单价:" + price);
				System.out.println("出产时间:" + time);
			}
		}
	@Test
	/**
	 * 创建元素并插入元素
	 * @throws Exception
	 */
	public void createAndInsert() throws Exception{
		Document document = getDocument();
//		创建元素
		Element newCarElement = document.createElement("汽车");
		newCarElement.setTextContent("我的汽车");
		Element rootElement = document.getDocumentElement();
		//rootElement.appendChild(newCarElement);
//		插入元素
		rootElement.insertBefore(
				newCarElement,
				rootElement.getElementsByTagName("汽车").item(1));
		write2xml(document);
	}
	@Test
	/**
	 * 修改元素
	 * @throws Exception
	 */
	public void update() throws Exception{
		Document document = getDocument();
		//获取元素
		Element secondCarElement = (Element) document.getElementsByTagName("汽车").item(1);
		//修改元素
		secondCarElement.getElementsByTagName("产地").item(0).setTextContent("深圳");
		secondCarElement.getElementsByTagName("车牌").item(0).getAttributes().getNamedItem("出产时间").setTextContent("2012年");
		write2xml(document);
	}
	@Test
	/**
	 * 删除元素
	 * @throws Exception
	 */
	public void delete() throws Exception{
		Document document = getDocument();
//		获取元素
		Element rootElement = document.getDocumentElement();
		Element secondCarElement = (Element) rootElement.getElementsByTagName("汽车").item(1);
		//删除元素
		rootElement.removeChild(secondCarElement);
		write2xml(document);
	}
	/**
	 *将Document写入xml
	 * @param document
	 * @throws Exception
	 */
	private void write2xml(Document document)throws Exception {
		//将内存中的document对象写到外存的xml文件
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer transformer = tf.newTransformer();
		//源
		Source source = new DOMSource(document);
		//目
		Result result = new StreamResult(new File("src/cn/feihzou/xml/dom/car.xml"));
		transformer.transform(source,result);
	}
	/**
	 * 获取Document对象
	 * @return
	 * @throws Exception
	 */
	private static Document getDocument() throws Exception {
//		得到创建 DOM 解析器的工厂。
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		//设置dom解析器将空白字符过滤
		factory.setIgnoringElementContentWhitespace(true);
		//DOM 解析器对象
		DocumentBuilder domParser = factory.newDocumentBuilder();
		Document document = domParser.parse(new File("src/cn/feihzou/xml/dom/car.xml"));
		return document;
	}
}






猜你喜欢

转载自blog.csdn.net/zhou920786312/article/details/82714459