您的位置:首页 > 编程语言 > Java开发

java xml操作

2015-12-31 11:40 573 查看
一、DOM(Document Object Model)
文档对象模型分析方式。以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取和操作文档的任意部分。是W3C的官方标准。
优点:
1、允许应用程序对数据和结构做出更改。
2、访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据
缺点:
1、通常需要加载整个XML文档来构造层次结构,消耗资源大。
二、SAX(Simple API for XML)
流模型中的推模型分析方式。通过事件驱动,每发现一个节点就引发一个事件,通过回调方法完成解析工作,解析XML文档的逻辑需要应用程序完成。
优点:
1、不需要等待所有数据都被处理,分析就能立即开始。
2、只在读取数据时检查数据,不需要保存在内存中。
3、可以在某个条件得到满足时停止解析,不必解析整个文档。
4、效率和性能较高,能解析大于系统内存的文档。
缺点:
1、需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),使用麻烦。
2、单向导航,很难同时访问同一文档的不同部分数据,不支持XPath。
三、JDOM(Java-based Document Object Model)
Java特定的文档对象模型。自身不包含解析器,使用SAX。
优点:
1、使用具体类而不是接口,简化了DOM的API。
2、大量使用了Java集合类,方便了Java开发人员。
缺点:
1、没有较好的灵活性。
2、性能较差。
四、DOM4J(Document Object Model for Java)
简单易用,采用Java集合框架,并完全支持DOM、SAX和JAXP。
优点:
1、大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
2、支持XPath。
3、有很好的性能。
缺点:
1、大量使用了接口,API较为复杂。
五、StAX(Streaming API for XML)
流模型中的拉模型分析方式。提供基于指针和基于迭代器两种方式的支持。
优点:
1、接口简单,使用方便。
2、采用流模型分析方式,有较好的性能。
缺点:
1、单向导航,不支持XPath,很难同时访问同一文档的不同部分。
==================================本文最后给出一个stax的各种解析的例子。 在文档最后哦!Java 6.0对XML支持的新特性有许多方面。比如StAX、针对XML-Web服务的Java架构(JAX-WS)2.0、针对XML绑定的API(JAXB)2.0、XML数字签名API,甚至还支持SQL:2003 'XML'数据类型。
##### WSDL的解析:wsdl4j schema的解析:DOM、DOM4J、Apache Schema项目、Xerces等 soapui jaxb :java对象与xml互相转换(JaxbContext)#########StAX是Streaming API for XML的缩写,是一种针对XML的流式拉分析API。关于对XML进行分析(或解析)的技术,大家一定都不陌生了。在Java 6.0之前,就已经有四种:
DOM:Document Object Model

SAX:Simple API for XML

JDOM:Java-based Document Object Model

DOM4J:Document Object Model for Java

推分析拉分析

在程序中访问和操作XML文件一般有两种模型:DOM(文档对象模型)和流模型。它们的优缺点如下:
引用DOM优点:允许编辑和更新XML文档,可以随机访问文档中的数据,可以使用XPath(XML Path Language,是一种从XML文档中搜索节点的查询语言)查询。
DOM缺点:需要一次性加载整个文档到内存中,对于大型文档,会造成性能问题。引用流模型优点:对XML文件的访问采用流的概念,在任何时候内存中只有当前节点,解决了DOM的性能问题。
流模型缺点:是只读的,并且只能向前,不能在文档中执行向后导航操作。流模型每次迭代XML文档中的一个节点,适合于处理较大的文档,所耗内存空间小。它有两种变体--“推”模型和“拉”模型。
引用推模型:就是我们常说的SAX,它是一种靠事件驱动的模型。当它每发现一个节点就引发一个事件,而我们需要编写这些事件的处理程序。这样的做法很麻烦,且不灵活。引用拉模型:在遍历文档时,会把感兴趣的部分从读取器中拉出,不需要引发事件,允许我们选择性地处理节点。这大大提高了灵活性,以及整体效率。StAX就是一种拉分析式的XML解析技术。它也支持对XML文件的生成操作。
从一开始,JAXP(Java API for XML Processing)就提供了两种方法来处理XML:DOM和SAX。StAX是一种面向流的新方法,最终版本于2004年3月发布,并成为JAXP 1.4(包含在Java 6.0中)的一部分。StAX的实现使用了JWSDP(Java Web Services Development Pack)1.6,并结合了SJSXP(Sun Java System XML Streaming Parser,位于javax.xml.stream.*包中)。
JWSDP是用来开发Web Services、Web应用程序以及Java应用(主要是XML处理)的开发包。它包含的Java API有:
JAXP:Java API for XML Processing

JAXB:Java Architecture for XML Binding

JAX-RPC:Java API for XML-based Remote Procedure Calls

JAX-WS:Java API for XML Web Services

SAAJ:SOAP with Attachments API for Java

JAXR:Java API for XML Registries

Web Services Registry

JWSDP的早期版本中还包括:
Java Servlet

JSP:JavaServer Pages

JSF:JavaServer Faces

现在,JWSDP已经被GlassFish所替代
StAX包括两套处理XML的API,分别提供了不同程度的抽象。它们是:基于指针的API和基于迭代器的API。先来了解基于指针的API。它把XML作为一个标记(或事件)流来处理,应用程序可以检查解析器的状态,获得解析的上一个标记的信息,然后再处理下一个标记,依次类推。<?xml version="1.0" encoding="UTF-8"?>

<company>

<depart title="Develop Group">

<user name="Tom" age="28" gender="male" >Manager</user>

<user name="Lily" age="26" gender="female" />

</depart>

<depart title="Test Group">

<user name="Frank" age="32" gender="male" >Team Leader</user>

<user name="Bob" age="45" gender="male" />

<user name="Kate" age="25" gender="female" />

</depart>

</company>

以让我们使用基于指针的API的接口是javax.xml.stream.XMLStreamReader(很遗憾,你不能直接实例化它),要得到它的实例,我们需要借助于javax.xml.stream.XMLInputFactory类。根据JAXP的传统风格,这里使用了抽象工厂(Abstract Factory)模式。如果你对这个模式很熟悉的话,就能够在脑海中想象出我们将要编写的代码的大致框架了。
首先,获得一个XMLInputFactory的实例。方法是:
XMLInputFactory factory = XMLInputFactory.newInstance();
或XMLInputFactory factory = XMLInputFactory.newFactory();

接下来我们就可以创建XMLStreamReader实例了:
try {

XMLStreamReader reader = factory.createXMLStreamReader(new FileReader("users.xml"));

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (XMLStreamException e) {

e.printStackTrace();

}

要遍历XML文档,需要用到XMLStreamReader的下面几个方法:
Java代码


int getEventType();

boolean hasNext() throws XMLStreamException;

int next() throws XMLStreamException;

getEventType()方法返回XMLStreamConstants接口中定义的一个标记常量,表示当前指针所指向标记(或事件)的类型。根据当前事件类型的不同,应用程序可以做出不同的处理。标记常量的类型和含义如下:

START_DOCUMENT:文档的开始

END_DOCUMENT:文档的结尾

START_ELEMENT:元素的开始

END_ELEMENT:元素的结尾

PROCESSING_INSTRUCTION:处理指令

CHARACTERS:字符(文本或空格)

COMMENT:注释

SPACE:可忽略的空格

ENTITY_REFERENCE:实体的引用

ATTRIBUTE:元素的属性

DTD:DTD

CDATA:CDATA块

NAMESPACE:命名空间的声明

NOTATION_DECLARATION:标记的声明

ENTITY_DECLARATION:实体的声明

对systemId稍作说明,并简单解释一下它与publicId的区别。
systemId和publicId是XML文档里DOCTYPE元素中经常出现的两个属性。它们都是对外部资源的引用,用以指明引用资源的地址。systemId是直接引用资源,publicId是间接定位外部资源。具体一点说是这样:
引用
systemId:外部资源(大多是DTD文件)的URI。比如本地文件file:///user/dtd/users.dtd或者网络某个地址的文件http://www.w3.org/dtd/users.dtd。引用publicId:相当于一个名字,这个名字代表了一个外部资源。比如,我们规定"W3C HTML 4.0.1"这个字符串对应"http://www.w3.org/dtd/users.dtd"这个资源。那么,publicId="W3C HTML 4.0.1"和systemId="http://www.w3.org/dtd/users.dtd"的作用就是一样的。我们的测试代码如下:
/**

* 列出所有用户

*

* @author zangweiren 2010-4-17

*

*/

public class ListUsers {

// 获得解析器

public static XMLStreamReader getStreamReader() {

String xmlFile = ListUsers.class.getResource("/").getFile()

+ "users.xml";

XMLInputFactory factory = XMLInputFactory.newFactory();

try {

XMLStreamReader reader = factory

.createXMLStreamReader(new FileReader(xmlFile));

return reader;

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (XMLStreamException e) {

e.printStackTrace();

}

return null;

}

// 列出所有用户名称

public static void listNames() {

XMLStreamReader reader = ListUsers.getStreamReader();

// 遍历XML文档

try {

while (reader.hasNext()) {

int event = reader.next();

// 如果是元素的开始

if (event == XMLStreamConstants.START_ELEMENT) {

// 列出所有用户名称

if ("user".equalsIgnoreCase(reader.getLocalName())) {

System.out.println("Name:"

+ reader.getAttributeValue(null, "name"));

}

}

}

reader.close();

} catch (XMLStreamException e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

ListUsers.listNames();

}

}

上面我们介绍了基于指针的StAX API。这种方式尽管效率高,但是没有提供XML结构的抽象,因此是一种低层API。
较为高级的基于迭代器的API允许应用程序把XML作为一系列事件对象来处理,每个对象和应用程序交换XML结构的一部分。应用程序只需要确定解析事件的类型,将其转换成对应的具体类型,然后利用其方法获得属于该事件对象的信息。
StAX中基于迭代器的API是一种面向对象的方式,这也是它与基于指针的API的最大区别。它通过将事件转变为对象,让应用程序可以用面向对象的方式处理它们,这有利于模块化和不同组件之间的代码重用。

事件迭代器API的主要接口是javax.xml.stream.XMLEventReader和javax.xml.stream.events.XMLEvent。XMLEventReader和XMLStreamReader相比要简单的多,这是因为关于解析事件的所有信息都封装在了事件对象(XMLEvent)中。
=========================================stax例子:/** * 利用java Stax API处理xml */@Testpublic void testStax1(){//本测试为stax的基于光标的xml处理XMLInputFactory factory = XMLInputFactory.newInstance();InputStream is = null ;is = TestStax.class.getClassLoader().getResourceAsStream("books.xml");try {XMLStreamReader reader = factory.createXMLStreamReader(is);while(reader.hasNext()){int type = reader.next();//判断节点类型(是否为 开始节点或结束节点或者文本节点)if(type == XMLStreamConstants.START_ELEMENT){System.out.println(reader.getName());//文本节点没有name//输出节点的属性(此处输出book的id)String name = reader.getName().toString();if(name.equals("book")){System.out.println(reader.getAttributeName(0)+" == "+reader.getAttributeValue(0));}}else if(type == XMLStreamConstants.CHARACTERS){//文本节点System.out.println(reader.getText().trim());}else if(type == XMLStreamConstants.END_ELEMENT){System.out.println(reader.getName());}}} catch (XMLStreamException e) {e.printStackTrace();}}@Testpublic void testStax2(){//本测试为stax的基于迭代的方式(XmlEventReader)XMLInputFactory factory = XMLInputFactory.newInstance();InputStream is = null ;is = TestStax.class.getClassLoader().getResourceAsStream("books.xml");try {//通过XMLEventReader来判断节点的类型XMLEventReader reader = factory.createXMLEventReader(is);while(reader.hasNext()){XMLEvent event = reader.nextEvent();//if(event.isStartElement()){String name = event.asStartElement().getName().toString();if(name.equals("book")){System.out.println(reader.getElementText());}}}} catch (XMLStreamException e) {e.printStackTrace();}}@Testpublic void testStax3(){//本测试为stax的基于过滤器方式:该方式可以有效地过滤掉不需要操作的节点,效率较高。XMLInputFactory factory = XMLInputFactory.newInstance();InputStream is = null ;is = TestStax.class.getClassLoader().getResourceAsStream("books.xml");try {//通过XMLEventReader来判断节点的类型XMLEventReader reader = factory.createFilteredReader(factory.createXMLEventReader(is), new EventFilter() {public boolean accept(XMLEvent event) {if(event.isStartElement()){return true ;}return false;}});while(reader.hasNext()){XMLEvent event = reader.nextEvent();//if(event.isStartElement()){String name = event.asStartElement().getName().toString();if(name.equals("book")){System.out.println(reader.getElementText());}}}} catch (XMLStreamException e) {e.printStackTrace();}}@Testpublic void testXpath(){//通过xpath处理xmlInputStream is = null ;try {is = TestStax.class.getClassLoader().getResourceAsStream("book.xml");DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();Document doc = db.parse(is);XPath xpath = XPathFactory.newInstance().newXPath();//创建xpathxpath.evaluate("//book[@id='bk102 ']", doc);//从源为doc的xml中找符合第一个参数(xpath表达式)的节点信息} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Testpublic void testStaxWriteAndModify(){//通过stax写xml 或者修改xmlInputStream is = null ;try {XMLStreamWriter xml = XMLOutputFactory.newInstance().createXMLStreamWriter(System.out);xml.writeStartDocument("GBK","1.0");xml.writeEndDocument();xml.writeStartElement("person");xml.writeStartElement("name");xml.writeCharacters("tom");xml.writeEndElement();//注意 每一个节点都要关闭,包括文本节点xml.writeEndElement();xml.flush();xml.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: