XML解析技术

XML解析技术

DOM技术:文档对象模型,需要将整个XML加入内存才能解析,占用内存比较多
SAX技术:一边加载,一边解析,一边释放内存,比较节省内存,基于推模式。
STAX技术:一种至于流的技术,和SAX技术很像,是基于拉模式的。

推模式与拉模式

推模式就好像服务器主动给你发送消息一样,当使用SAX技术时,xml解析器碰到一个标签就会触发一个事件,而且一旦开始解析就不会停下来,知道所有内容解析完毕,不能人为的控制解析过程。

拉模式类似客户端发起HTTP请求后服务器才发送内容,使用STAX技术时,会碰到一个标签解析一下然后停止解析,如果还需要解析的话必须人为的启动解析,就好像解析器开启懒人模式一样。

基于以上技术实现的解析工具有
JAXP 同时支持DOM SAX STAX三种技术
DOM4J 支持DOM解析方式
XML PULL   android移动设备内置的xml解析技术, 支持STAX解析方式 

技术选择

在javaee开发中通常使用DOM技术,编程简单。当xml文档过于大时,优先使用SAX/STAX技术。

JAXP解析代码

DOM解析API
全局查找
通过ID查找            getElementById()     //无约束的DTD文档不能使用该方法
通过标签名查找    getElementsByTagName()
相对节点位置查找
getChildNodes():         返回这个节点的所有子节点列表
getFirstChild():        返回这个节点的第一个子节点
getParentNode():    返回这个节点的父节点对象
getPreviousSibling():     返回其前一个兄弟节点
getNextSibling():          返回该节点下一个兄弟节点

DOMTest.java

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 DOMTest {
@Test
public void demo1() throws ParserConfigurationException, SAXException,
IOException {
// 构造工厂
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
// 通过工厂获得解析器
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 使用解析器加载xml文档
Document document = builder.parse("books.xml");
// 通过标签名获得元素
NodeList nodeList = document.getElementsByTagName("name");
for (int i = 0; i < nodeList.getLength(); i++) {
Element e = (Element) nodeList.item(i);
// 获取标签名称
System.out.println(e.getNodeName());
// 获取<name>标签子节点
System.out.println(e.getFirstChild().getNodeValue());
// 获取<name>标签类型
System.out.println(e.getNodeType());
}
}
}

books.xml
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book>
<name>adfafd</name>
<price>123</price>
</book>
<book>
<name>dfadfe</name>
<price>2321</price>
</book>
</books>
         
DOM的增加节点操作
public void DOM2Test() throws ParserConfigurationException, SAXException,
IOException, TransformerException,
TransformerConfigurationException {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
// 通过工厂获得解析器
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 使用解析器加载xml文档
Document document = builder.parse("books.xml");
// 创建元素节点
Element time = document.createElement("time");
// 设置节点包含的文本内容
time.setTextContent("2015-12-28");
// 获取欲加入位置
NodeList nodeList = document.getElementsByTagName("name");
//将节点<time>加入到<name>下
nodeList.item(0).appendChild(time);
// 将新的DOM对象重新写会原文件
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
StreamResult streamResult = new StreamResult(new File("books.xml"));
transformer.transform(domSource, streamResult);
}


DOM修改节点
public void DOM2Test() throws ParserConfigurationException, SAXException,
IOException, TransformerException,
TransformerConfigurationException {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
// 通过工厂获得解析器
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 使用解析器加载xml文档
Document document = builder.parse("books.xml");
// 获取欲修改位置
NodeList nodeList = document.getElementsByTagName("name");
int nodeListLength = nodeList.getLength();
for (int i = 0; i < nodeListLength; i++) {
Element e = (Element) nodeList.item(i);
if (e.getTextContent().equals("java编程思想")) {
String oldPrice = e.getNextSibling().getTextContent();
int newPrice = (int) (Integer.parseInt(oldPrice) * 1.5);
e.getNextSibling().setTextContent(String.valueOf(newPrice));
}
}
// 将新的DOM对象重新写会原文件
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
StreamResult streamResult = new StreamResult(new File("books.xml"));
transformer.transform(domSource, streamResult);
}


DOM的删除操作
public void DOM2Test() throws ParserConfigurationException, SAXException,
IOException, TransformerException,
TransformerConfigurationException {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
// 通过工厂获得解析器
DocumentBuilder builder = builderFactory.newDocumentBuilder();
// 使用解析器加载xml文档
Document document = builder.parse("books.xml");
// 获取欲修改位置
NodeList nodeList = document.getElementsByTagName("name");
int nodeListLength = nodeList.getLength();
for (int i = 0; i < nodeListLength; i++) {
Element e = (Element) nodeList.item(i);
System.out.println(e.getTextContent());
if (e.getTextContent().equals("java编程思想")) {
e.getParentNode().removeChild(e);
//<name>节点被删除后,<price>节点成为第一个节点,所以要减1
i--;
}
}
// 将新的DOM对象重新写会原文件
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
StreamResult streamResult = new StreamResult(new File("books.xml"));
transformer.transform(domSource, streamResult);
}
}


SAX是基于事件驱动的XML处理方法
当SAX解析器标签的起始标记时会回调starElement()方法,比如遇到了<p>标签就会回调该方法
endElement()函数是遇到结束标签时调用该方法

SAX测试代码:
复写DefaultHandler类
package com.donyu.www;

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


public class MyHandler extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
System.out.println("start Document...");
}


@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println(qName);
if (qName.equals("book"))
//标签的属性以键值对方式存储
System.out.println("id属性为:" + attributes.getValue("id"));
}


@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String string = new String(ch, start, length);
System.out.println("start character..." + string);
}


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


@Override
public void endDocument() throws SAXException {
System.out.println("end Document...");
}
}

@Test
public void SAXTest() throws ParserConfigurationException, SAXException,
IOException {
// 创建解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
// 创建解析器
SAXParser saxParser = factory.newSAXParser();
// 初始化回调函数
MyHandler handler = new MyHandler();
//将解析的文档和回调函数一并传入
saxParser.parse("books.xml", handler);
}


STAX测试代码:
测试文档为上面的books.xml
@Test
public void TestPull() throws XmlPullParserException, IOException {
// 创建工厂
XmlPullParserFactory pullParserFactory = XmlPullParserFactory
.newInstance();
// 通过工厂获得解析器
XmlPullParser pullParser = pullParserFactory.newPullParser();
// 将XML文档传入
pullParser.setInput(new FileInputStream("books.xml"), "utf-8");
// 获取事件类型
while (pullParser.getEventType() != XmlPullParser.END_DOCUMENT) {
if (pullParser.getEventType() == XmlPullParser.START_TAG) {
if (pullParser.getName().equals("name"))
System.out.println(pullParser.nextText());
}
pullParser.next();
}
}

使用XML PULL生成XML文档
public void SerializerTest() throws XmlPullParserException,
IllegalArgumentException, IllegalStateException,
FileNotFoundException, IOException {
XmlPullParserFactory pullParserFactory = XmlPullParserFactory
.newInstance();
XmlSerializer serializer = pullParserFactory.newSerializer();
// 设置序列化文档
serializer.setOutput(new FileOutputStream("books_blank.xml"), "utf-8");
serializer.startDocument("utf-8", true);
serializer.startTag(null, "admin");
serializer.startTag(null, "username");
serializer.text("root");
serializer.endTag(null, "username");
serializer.endTag(null, "admin");
serializer.endDocument();
}
由于SAX和STAX技术对XML解析一部分后直接释放内存,再将下一部分装入内存,所以我们无法使用SAX或STAX来直接修改XML文档,可以先用SAX解析后转换成多个对象(用ArrayList存储),然后这些对象进行修改,在用序列化方式,写到文本文件中去。

 

转载于:https://www.cnblogs.com/xidongyu/p/6371803.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值