您的位置:首页 > 其它

JAXP解析XML(基于DOM模型)

2014-04-21 19:52 357 查看
对于XML解析通常分为两种:

1.DOM解析(Document Object Model,文档对象模型),该方式是W3C 组织推荐的处理 XML 的一种方式。

2.另一种是SAX(Simple API for XML)。

当然IBM公司后面退出了JAXB,基于JavaBean的XML解析方式,不过本文描述的是DOM模型解析原理以及使用Java内置的API(JAXP---Java API for XML Processing)通过DOM模型来解析XML,因为JAXP作为JavaEE规范中的一种技术,所以作为一个Java程序猿来说掌握这套API是必须的

一:什么是DOM?

Document Object Model(文档对象模型),它是W3C 组织推荐的处理 XML 的一种方式。

DOM模型定义访问和操作XML文档的标准方法。(即定义一种访问XML文档一种规范)

下面来看一份XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<!--将DTD文件编写在XML文档内部-->
<!DOCTYPE bookstore [
<!ELEMENT bookstore (book)+>
<!ELEMENT book (title,author,year,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST book category CDATA #REQUIRED>
<!ATTLIST title lang CDATA #REQUIRED>
]>

<bookstore>
<book category="操作系统">
<title lang="中文">鸟哥的私房菜</title>
<author>鸟哥</author>
<year>2005</year>
<price>89.5</price>
</book>
</bookstore>


这是一份有效(格式良好,且有DTD约束)的XML文档。

当我们使用DOM方式去解析该XML文档的时候,XML文档会在内存中形成一个树形结构,而XML 文档中的每个成分都是一个节点



这里特别要注意的是:

W3C组织对DOM是这样定义的:

整个文档是一个文档节点(Document)

XML中的每个标签都是元素节点(Element Node)

XML中的每个文本都是文本节点(Text Node)

XML中的标签属性都是属性节点(Attr Node)

XML中的注释被称为注释节点(Comment Node)

文本总是存储在文本节点中,而不是存储在元素节点中的,在 DOM 处理中一个普遍的错误是,认为元素节点包含文本。

不过,元素节点的文本是存储在文本节点中的。

在这个例子中:<year>2005</year>,元素节点 <year>,拥有一个值为 "2005" 的文本节点。

"2005" 不是 <year> 元素的值!

最后需要注意的是:由于解析器会将XML文档中的所有节点都加载到内存之中,所以可以很方便的完成CRUD操作,但是此方法也过于暴力,当XML文档内容过大时,可能会造成内存溢出的情况,这点大家都应该很清楚。

二:使用JAXP采用DOM编程模型解析XML.

解析XML的本质是通过解析器去完成的,但是我们并不是直接去调用解析器的方法去操作XML文档.而是SUN公司为我们提供了一套API让我们调用,与解析器交互的事情由SUN公司帮助我们完成.

package cn.plx.jaxp;

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.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* 使用SUN提供的JAXP解析XML文档
*
* @author Administrator
*
*/
public class JAXPTest {

public static void main(String[] args) throws Exception {
// 创建XML解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
/*
* om.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
* xerces是由IBM公司提供的XML解析器
*/
System.out.println(factory.getClass().getName());

// 创建XML解析器
DocumentBuilder builder = factory.newDocumentBuilder();
System.out.println(builder.getClass().getName());

/**
* <pre>
* 获取到Document对象,Document对象代表着DOM树的根节点
* 使用Document对象可以对XML文档的数据进行基本操作
* Document对象在DOM解析模型中也属于一个Node对象,
* 它是其他Node对象所在的上下文,其他Node对象包括
* Element,Text,Attr,Comment,Processing Instruction等等
* 根节点 != 根元素,它们是包含关系
* </pre>
*/
Document document = builder.parse(new File("xml/book.xml"));

/**
* <pre>
* 获取到XML文档的根元素
* 对于XML中的Document是XML文档的根节点,而它的子元素是XML文档的XML文档根元素
* </pre>
*/
Element root = document.getDocumentElement();
System.out.println("获取的XML文档的根元素节点:" + root.getTagName());

/**
* <pre>
* 获取根元素节点的子节点
* 对于XML文档而言,无论是Document,Elment,Text等等,
* 它们在DOM解析模型中都属性一个Node,因此这里需要注意的一点是
* 空白字符在DOM解析中也会被作为一个Node元素来处理。
* </pre>
*/
// 获取到根元素的子节点
NodeList nodeList = root.getChildNodes();

/*
* 空白字符也会被当作子节点来处理,因为它也是一个Node来处理, 但是属性不会被作为子节点
*/
System.out.println("子节点的个数为:" + nodeList.getLength());

// 遍历所有的子节点
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
switch (node.getNodeType()) {
case Node.ELEMENT_NODE:
System.out.println("获取的是元素:" + node.getNodeName());
break;
case Node.TEXT_NODE:
System.out.println("获取的是文本" + node.getNodeName());
break;
case Node.COMMENT_NODE:
System.out.println("获取的是注释:" + node.getNodeName());
Comment comment = (Comment) node;
System.out.println("注释的内容是:" + comment.getData());
break;
}
}

System.out.println("--------访问属性----------");
// 访问属性
Attr attr = root.getAttributeNode("名字");
System.out.println("根元素节点属性的值:" + attr.getValue());

// 可以是使用一种更加直接的方式访问属性的值
String attrValue = root.getAttribute("名字");
System.out.println("另一种方式获取根元素节点属性的值:" + attrValue);

// 获取元素的全部属性
NamedNodeMap attrs = root.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Attr attr2 = (Attr) attrs.item(i);
System.out.println("name:" + attr2.getName() + ",value:"
+ attr2.getValue());
}

}

/**
* <pre>
* 使用JAXP完成添加元素节点操作
* 对于DOM解析模型来说,因为XML文档的上下文是Document对象
* 所以对于XML文档的操作都使用Document对象来完成
* </pre>
*/
@Test
public void addElementTest() throws Exception {

// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

// 创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();

// 获取XML文档的根节点(root node)
Document document = builder.parse(new File("xml/book2.xml"));

// 返回新创建的Element节点
Element book = document.createElement("书");

Element bookName = document.createElement("书名");
bookName.setTextContent("Liunx");

Element author = document.createElement("作者");
author.setTextContent("XXX");

Element price = document.createElement("价格");
price.setTextContent(String.valueOf(80.5));

// 通过父元素添加子元素
book.appendChild(bookName);
book.appendChild(author);
book.appendChild(price);

document.getDocumentElement().appendChild(book);

TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
new File("xml/book2.xml")));
}

/**
* 更新节点元素
*/
@Test
public void updateElementTest() throws Exception {

// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

// 创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();

// 获取XML文档的根节点(root node)
Document document = builder.parse(new File("xml/book2.xml"));

// 获取第3个价格元素
Node priceNode = document.getElementsByTagName("价格").item(2);
// 判断是否是Element类型
if (priceNode.getNodeType() == Node.ELEMENT_NODE) {
priceNode.setTextContent("200");
}

TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
new File("xml/book2.xml")));
}

@Test
public void deleteElementTest() throws Exception {
// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

// 创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();

// 获取XML文档的根节点(root node)
Document document = builder.parse(new File("xml/book2.xml"));

Node node = document.getElementsByTagName("书").item(2);

document.getDocumentElement().removeChild(node);

TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
new File("xml/book2.xml")));
}

/**
* 添加子元素到到指定位置
* @throws Exception
*/
@Test
public void insertElementTest() throws Exception{

// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

// 创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();

// 获取XML文档的根节点(root node)
Document document = builder.parse(new File("xml/book2.xml"));

// 返回新创建的Element节点
Element book = document.createElement("书");

Element bookName = document.createElement("书名");
bookName.setTextContent("Liunx");

Element author = document.createElement("作者");
author.setTextContent("XXX");

Element price = document.createElement("价格");
price.setTextContent(String.valueOf(80.5));

// 通过父元素添加子元素
book.appendChild(bookName);
book.appendChild(author);
book.appendChild(price);

document.getDocumentElement().insertBefore(book, document.getElementsByTagName("书").item(1));

TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
new File("xml/book2.xml")));
}

/**
* 添加属性
* @throws Exception
*/
@Test
public void addAttrTest() throws Exception{

// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

// 创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();

// 获取XML文档的根节点(root node)
Document document = builder.parse(new File("xml/book2.xml"));

Node node = document.getElementsByTagName("书").item(1);
if(node.getNodeType() == Node.ELEMENT_NODE){
Element element  = (Element) node;
element.setAttribute("名称","Java开发");
}
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
new File("xml/book2.xml")));
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: