03-JavaWeb-XML-xml编程-dom解析

XML编程(CRUD)

一, XML解析技术概述

1, XML解析方式分为两种
    dom, sax
2, dom:
    Document Object Model, 即文档对象模型
    是 W3C 组织推荐的处理 XML 的一种方式。
3, sax
    Simple API for XML, 不是官方标准,
    但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。
4, XML解析器
    Crimson(SUN)、Xerces(IBM) 、Aelfred2(DOM4J)
    jdk1.5 以前, 使用的是 Crimson
    jdk1.5 开始, 使用的是 Xerces
5, XML解析开发包
    Jaxp(SUN)、Jdom、dom4j(性能最好)
    直接使用解析器对开发者来说是很困难的, 
    因此提供相应的API对解析器进行包装.


二, 两种解析方式

DOM解析

1, 如图

DOM解析, 所有的结点都会被解析为对象
标签 --> org.w3c.dom.Element 对象
文本 --> org.w3c.dom.Text 对象
属性 --> org.w3c.dom.Attr 对象


2, 

Node
  |-- Document
  |-- Element
  |-- Text
  |-- Attr


3, 

一把使用Node操作结点,
当Node方法不够用时, 强转成对应的扩展类型.


4, 优缺点

①优
    使用DOM解析xml文档, 实现CRUD特别方便, 操作速度快.
②缺
    如果xml文件比较大, 对内存消耗特别大, 极容易导致内存溢出.
    不适合操作大的xml文档.


5, 调整JVM内存

JDK1.7 -> 图(Java) -> Non-Standard Options(非标准选项)
C:> java -Xmx512M HelloWorld


SAX解析

1, 读取一行解析一样
2, 优缺点
①优
    解析速度很快, 对内存消耗很小
②缺
    只适合查找数据, 不适合进行 增删改.


三, JAXP -DOM解析

1, 概述

    JAXP 开发包是J2SE的一部分,
    它由javax.xml、org.w3c.dom 、org.xml.sax 包及其子包组成
    在 javax.xml.parsers 包中,定义了几个工厂类,
    程序员调用这些工厂类,可以得到对xml文档进行解析的 DOM 或 SAX 的解析器对象。


2, 使用JAXP进行DOM解析

    javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 , 
    DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,
    但该类提供了一个newInstance方法 ,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。


3, 获得JAXP中的DOM解析器

// 1, 获取解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();


// 2, 获取解析器
DocumentBuilder parser = factory.newDocumentBuilder();


// 3, 解析xml文档,得到代表文档的document对象
Document document = parser.parse(new File("src/jaxp/dom/book.xml"));



4, DOM模型(document object model)

(1) 概述
    DOM解析器在解析XML文档时,会把文档中的所有元素,
    按照其出现的层次关系,解析成一个个Node对象(节点)。
(2) 在dom中,节点之间关系如下:
① 位于一个节点之上的节点是该节点的 父节点(parent)
② 一个节点之下的节点是该节点的 子节点(children) 
③ 同一层次,具有相同父节点的节点是 兄弟节点(sibling) 
④ 一个节点的下一个层次的节点集合是 节点后代(descendant)
⑤父、祖父节点及所有位于节点上面的,都是节点的 祖先(ancestor) 
(3) 节点类型
① Node对象提供了一系列常量来代表结点的类型,
   当开发人员获得某个Node类型后,就可以把Node节点转换成相应的节点对象(Node的子类对象),
   以便于调用其特有的方法。(查看API文档) 
   ATTRIBUTE_NODE  该节点为 Attr。
   CDATA_SECTION_NODE  该节点为 CDATASection。
   COMMENT_NODE  该节点为 Comment。
   ... ...
② Node对象提供了相应的方法去获得它的父结点或子结点。
   编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容了。


5, 更新XML文档

(1) javax.xml.transform包中的Transformer类
    用于把代表XML文件的Document对象转换为某种格式后进行输出,
    例如把xml文件应用样式表后转成一个html文档。
    利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
(2) Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。
    我们可以通过:
    javax.xml.transform.dom.DOMSource类来关联要转换的document对象, 
    javax.xml.transform.stream.StreamResult 对象来表示数据的目的地。
(3) Transformer对象通过TransformerFactory获得。
(4) 例子

// 写入内存
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(new File("src/jaxp/dom/book.xml")));


解析XML的CRUD

1, book.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<书架>
	<书 name="xxx">
		<书名>Java就业培训教程</书名>
		<售价>11元</售价>
		<售价>59.00元</售价>
		<作者>张孝祥</作者>

	</书>
	<书>
		<书名>JavaScript网页开发</书名>
		<作者>张孝祥</作者>
		<售价>28.00元</售价>
	</书>
</书架>


2, Demo1.java

package jaxp.dom;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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.Node;
import org.w3c.dom.NodeList;
/**
 *  用JAXP 以DOM方式操作 xml
 */
public class Demo1 {

	@Test
	public void setUp() throws Exception {
		
		// 1, 获取解析器工厂
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		
		// 2, 产生解析器
		DocumentBuilder parser = factory.newDocumentBuilder();
		
		// 3, 解析xml文档,得到代表文档的document对象
		Document document = parser.parse(new File("src/jaxp/dom/book.xml"));
		
		System.out.println(document);
	}
	
	
	@Test
	// 得到售价节点的值
	public void read() throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder parser = factory.newDocumentBuilder();
		Document document = parser.parse(new File("src/jaxp/dom/book.xml"));
		
		NodeList nodes = document.getElementsByTagName("售价");
		Node price = nodes.item(0);
		String value = price.getTextContent();
		System.out.println(value);
	}
	
	@Test
	// 修改结点的值: <售价>39.00元</售价> -> <售价>59.00元</售价>
	public void update() throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(new File("src/jaxp/dom/book.xml"));
		
		Node price = document.getElementsByTagName("售价").item(0);
		price.setTextContent("59.00元");
		
		// 把内存中的document写到xml文档
		// 1, 转换器工厂
		TransformerFactory tFactory = TransformerFactory.newInstance();
		// 2, 得到转换器
		Transformer transformer = tFactory.newTransformer();
		// 3, 将内存中的document写入指定文件 
		transformer.transform(new DOMSource(document) , new StreamResult(new File("src/jaxp/dom/book.xml")) );
	}

	@Test
	// 末尾 添加新结点   <售价>11元</售价>
	public void add() throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document  document = builder.parse("src/jaxp/dom/book.xml");
		
		// 创建新结点   <售价>11元</售价>
		Element price = document.createElement("售价");
		price.setTextContent("11元");
		
		// 得到需要增加结点的父亲
		Element parent = (Element) document.getElementsByTagName("书").item(0);
		
		// 将 新结点 挂载到父节点上
		parent.appendChild(price);
		
		// 写入内存
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer = tFactory.newTransformer();
		transformer.transform(new DOMSource(document), new StreamResult(new File("src/jaxp/dom/book.xml")));
	}
	
	@Test
	// 指定位置<售价>59.00元</售价> 之前,  添加新结点   <售价>11元</售价>
	public void add_2() throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(new File("src/jaxp/dom/book.xml"));
		
		// 创建新结点 <售价>11元</售价>
		Element newPrice = document.createElement("售价");
		newPrice.setTextContent("11元");
		
		// 获取父节点
		Element parent = (Element) document.getElementsByTagName("书").item(0);
		
		// 获取指定结点
		Node refChild = parent.getElementsByTagName("售价").item(0); 
		
		// 添加到指定结点的后面
		parent.insertBefore(newPrice, refChild);
		
		// 写到xml中
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer = tFactory.newTransformer();
		transformer.transform(new DOMSource(document), new StreamResult(new File("src/jaxp/dom/book.xml")));
	}
	
	@Test
	// 删除结点   <售价>11元</售价>
	public void delete() throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(new File("src/jaxp/dom/book.xml"));
		/*
		// 得到需要增加结点的父亲
		Element parent = (Element) document.getElementsByTagName("书").item(0);
		
		// 得到需要删除的结点
		Element child = (Element) parent.getElementsByTagName("售价").item(1);
		
		// 删除  <售价>11元</售价>
		parent.removeChild(child);
		*/
		
		// 得到需要删除的结点
		Node node = document.getElementsByTagName("售价").item(0);
		
		// 删除
		node.getParentNode().removeChild(node);
		
		// 写入内存
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer = tFactory.newTransformer();
		transformer.transform(new DOMSource(document), new StreamResult(new File("src/jaxp/dom/book.xml")));
	}
	
	@Test
	//更新 xml文档属性, <书 name="xxx">  -> <书 name="yyy">
	public void updateAttribute() throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(new File("src/jaxp/dom/book.xml"));
		/*
		// 获取指定结点
		Element book = (Element) document.getElementsByTagName("书").item(0);
		// 获取指定结点 的属性
		Attr nameAttr = book.getAttributeNode("name");
		
		// 更新
		nameAttr.setTextContent("yyy");*/
		
		// 获取指定结点
		Element book = (Element) document.getElementsByTagName("书").item(0);
		
		// 更改
		book.setAttribute("name", "yyy");
		// 增加
		book.setAttribute("password", "123");
		// 删除
		book.removeAttribute("name");
		
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer  transformer = tFactory.newTransformer();
		transformer.transform(new DOMSource(document), new StreamResult(new File("src/jaxp/dom/book.xml")));
	}
	
	//遍历
	private void list(Node node) throws Exception {
		
		
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			System.out.println(node.getNodeName());
		}
		
		if ( !node.hasChildNodes()) {
			if ("".equals(node.getTextContent().trim())) {
				return;
			}
			System.out.println(" " + node.getTextContent());
			return;	
		}
		
		NodeList children = node.getChildNodes();
		
		for (int i = 0; i < children.getLength(); i++) {
			list(children.item(i));
		}
	}
	
	@Test
	public void traverseXml() throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(new File("src/jaxp/dom/book.xml"));
		
		list(document);
	}
	
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值