java操作xml解析技术_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解析代码

JAXP(Java API for XML Processing)提供了DOM和SAX的接口,因此可用其对XML文件进行解析。以下面的XML文件为例,说明JAXP的使用方式。

XML文件

adfafd

123

dfadfe

2321

DOM解析API

全局查找

通过ID查找 getElementById() //无约束的DTD文档不能使用该方法

通过标签名查找 getElementsByTagName()

相对节点位置查找

getChildNodes(): 返回这个节点的所有子节点列表

getFirstChild(): 返回这个节点的第一个子节点

getParentNode(): 返回这个节点的父节点对象

getPreviousSibling(): 返回其前一个兄弟节点

getNextSibling(): 返回该节点下一个兄弟节点

DOM读取XML文件

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

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());

// 获取标签子节点

System.out.println(e.getFirstChild().getNodeValue());

// 获取标签类型

System.out.println(e.getNodeType());

}

}

}

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");

//将节点加入到下

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);

//节点被删除后,节点成为第一个节点,所以要减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

SAX是基于事件驱动的XML处理方法,当SAX解析器标签的起始标记时会回调starElement()方法,比如遇到了

标签就会回调该方法,endElement()函数是遇到结束标签时调用该方法。

SAX测试代码:

首先需要复写DefaultHandler类

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...");

}

构建解析器进行解析,解析器在进行解析时,会调用Handler中的方法进行处理

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

STAX模式在Android中使用,因此下面的代码只能在Android环境下运行

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();

}

总结

由于DOM是将整个XML装载进内存,因此可以直接在内存直接操作XML文件。由于SAX和STAX技术对XML解析一部分后直接释放内存,再将下一部分装入内存,所以我们无法使用SAX或STAX来直接修改XML文档,可以先用SAX解析后转换成多个对象(用ArrayList存储),然后这些对象进行修改,在用序列化方式,写到文本文件中去。因此DOM多用于写场景,而SAX/STAX多用于读场景。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值