XML---解析

xml解析

a) DOM:DOM 解析器把 XML 文档转化为一个包含其内容的树,并能够对树进行遍历。用 DOM 解析模型的长处是编程容易,能够很容易的添加和修改树中的元素。然而

    由于使用 DOM 解析器的时候需要处理整个 XML 文档,所以对性能和内存的需要比较高,尤其是碰到很大的 XML 文档的时候。

b)SAX:SAX 解析器采用了基于事件的模型(在解析 XML 文档的时候能够触发一系列的事件,当发现给定的tag的时候,他能够激活一个回调方法,告诉该方法定制的标

签已找到)。因为他让程序员自己来决定所要处理的tag,所以当只需要处理文档中所包含的部分数据时,SAX 有良好的表现。但用 SAX 解析器的时候编码工作会比较困

难,而且很难同时访问同一个文档中的多处不同数据。

c)JDOM:JDOM的目的是成为 Java 特定文档模型,他简化和 XML 的交互并且比使用 DOM 实现更快。

d)DOM4J:DOM4J 是很优秀的Java XML API,具备性能优异、功能强大和极端易用使用的特点,同时他也是个开放源代码的软件。

1dom解析

DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程

序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口

的机制也被称作随机访问机制。

DOM接口提供了一种通过分层对象模型来访问XML文档信息的方式,这些分层对象模型依据XML的文档结构形成了一棵节点树。无论XML文档中所描述的是什么类型的信息,

即便是制表数据、项目列表或一个文档,利用DOM所生成的模型都是节点树的形式。也就是说,DOM强制使用树模型来访问XML文档中的信息。由于XML本质上就是一种分

层结构,所以这种描述方法是相当有效的。DOM树所提供的随机访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。然而,由于DOM

分析器把整个XML文档转化成DOM树放在了内存中,因此,当文档比较大或者结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作

所以,DOM分析器对机器性能的要求比较高,实现效率不十分理想。不过,由于DOM分析器所采用的树结构的思想与XML文档的结构相吻合,同时鉴于随机访问所带来的方

便,因此,DOM分析器还是有很广泛的使用价值的。

1.1dom组成

对于XML应用开发来说,DOM就是一个对象化的XML数据接口,一个与语言无关、与平台无关的标准接口规范。它定义了HTML文档和XML文档的逻辑结构,给出了一种

访问和处理HTML文档和XML文档的方法。利用DOM,程序开发人员可以动态地创建文档,遍历文档结构,添加、修改、删除文档内容,改变文档的显示方式等等。可以这样

说,文档代表的是数据,而DOM则代表了如何去处理这些数据。无论是在浏览器里还是在浏览器外,无论是在服务器上还是在客户端,只要有用到XML的地方,就会碰到对

DOM的应用。

作为W3C 的标准接口规范, 目前, DOM 由三部分组成, 包括: 核心(core )、HTML和XML。核心部分是结构化文档比较底层对象的集合,这一部分所定义的对象已经完全

可以表达出任何HTML和XML文档中的数据了。HTML接口和XML接口两部分则是专为操作具体的HTML文档和XML文档所提供的高级接口,使对这两类文件的操作更加方便。

1.2dom模型结构

1.3dom的四大接口

在DOM接口规范中,有四个基本的接口:Document,Node,NodeList以及NamedNodeMap。在这四个基本接口中,Document接口是对文档进行操作的入口,它是从

Node接口继承过来的。Node接口是其他大多数接口的父类,像Document,Element,Attribute,Text,Comment等接口都是从Node接口继承过来的。NodeList接口是一个节点

的集合,它包含了某个节点中的所有子节点。NamedNodeMap接口也是一个节点的集合,通过该接口,可以建立节点名和节点之间的一一映射关系,从而利用节点名可以直接

访问特定的节点。

a)Document接口

由于元素、文本节点、注释、处理指令等都不能脱离文档的上下文关系而独立存在,所以在Document接口提供了创建其他节点对象的方法,通过该方法创建的节点对象都有一

个ownerDocument属性,用来表明当前节点是由谁所创建的以及节点同Document之间的联系。

b)Node接口

Node接口在整个DOM树中具有举足轻重的地位,DOM接口中有很大一部分接口是从Node接口继承过来的,例如,Element、Attr、CDATASection等接口,都是从Node继承过来

的。在DOM树中,Node接口代表了树中的一个节点。

例:(利用DOM解析如下XML)
<?xml version="1.0"?>
<PEOPLE>
<PERSON PERSONID="E01">
<NAME>ivan</NAME>
<ADDRESS>dalian</ADDRESS>
<EMAIL>ivan@163.com</EMAIL>
</PERSON>
<PERSON PERSONID="E02">
<NAME>lisa</NAME>
<ADDRESS>beijing</ADDRESS>
<EMAIL>lisa@163.com</EMAIL>
</PERSON>
<PERSON PERSONID="E03">
<NAME>grace</NAME>
<ADDRESS>shanghai</ADDRESS>
<EMAIL>grace@163.com</EMAIL>
</PERSON>
</PEOPLE>
Java代码如下:

public static void main(String[] args) throws Exception
{
// step 1: 获得dom解析器工厂
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
// step 2:获得具体的dom解析器
DocumentBuilder db = dbf.newDocumentBuilder();
// step3: 解析一个xml文档,获得Document对象(根结点)
Document document = db.parse(new File("persons.xml"));
NodeList list = document.getElementsByTagName("PERSON");
for(int i = 0; i < list.getLength(); i++)
{
Element element = (Element)list.item(i);
String content =
element.getElementsByTagName("NAME").item(0).getFirstChild().g
etNodeValue();
System.out.println("name:" + content);
content =
element.getElementsByTagName("ADDRESS").item(0).getFirstChild().g
etNodeValue();
System.out.println("address:" + content);
content =
element.getElementsByTagName("EMAIL").item(0).getFirstChild().get
NodeValue();
System.out.println("email:" + content);
}
}

例:xml通用的解析(递归)
public static void main(String[] args) throws Exception
{
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File("persons.xml"));
Element root = doc.getDocumentElement();
parseElement(root);
}
private static void parseElement(Element element)
{
String tagName = element.getNodeName();
NodeList children = element.getChildNodes();
System.out.print("<" + tagName);
//element元素的所有属性所构成的NamedNodeMap对象,需要对其进行判断
NamedNodeMap map = element.getAttributes();
//如果该元素存在属性
if(null != map)
{
for(int i = 0; i < map.getLength(); i++)
{
//获得该元素的每一个属性
Attr attr = (Attr)map.item(i);
String attrName = attr.getName();
String attrValue = attr.getValue();
System.out.print(" " + attrName + "=\"" + attrValue
+ "\"");
}
}
System.out.print(">");
for(int i = 0; i < children.getLength(); i++)
{
Node node = children.item(i);
//获得结点的类型
short nodeType = node.getNodeType();
if(nodeType == Node.ELEMENT_NODE)
{
//是元素,继续递归
parseElement((Element)node);
}
else if(nodeType == Node.TEXT_NODE)
{
//递归出口
System.out.print(node.getNodeValue());
}
else if(nodeType == Node.COMMENT_NODE)
{
System.out.print("<!--");
Comment comment = (Comment)node;
//注释内容
String data = comment.getData();
System.out.print(data);
System.out.print("-->");
}
System.out.print("</" + tagName + ">");
}
2sax解析

SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分

析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口.

SAX分析器在对XML文档进行分析时,触发了一系列的事件,由于事件触发本身是有时序性的,因此,SAX提供的是一种顺序访问机制,对于已经分析过的部分,不能再倒回

去重新处理。SAX之所以被叫做"简单"应用程序接口,是因为SAX分析器只做了一些简单的工作,大部分工作还要由应用程序自己去做。也就是说,SAX分析器在实现时,它只

是顺序地检查XML文档中的字节流,判断当前字节是XML语法中的哪一部分、是否符合XML语法,然后再触发相应的事件,而事件处理函数本身则要由应用程序自己来实现。同

DOM分析器相比,SAX分析器缺乏灵活性。然而,由于SAX分析器实现简单,对内存要求比较低,因此实现效率比较高,对于那些只需要访问XML文档中的数据而不对文档进

行更改的应用程序来说,SAX分析器更为合适。

2.1SAX分析器的大体构成框架

例:解析xml

public static void main(String[] args) throws Exception
{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(new File("student.xml"), new MyHandler2());
}
}
class MyHandler2 extends DefaultHandler
{
private Stack<String> stack = new Stack<String>();
private String name;
private String address;
private String email;
@Override
public void startElement(String uri, String localName, String
qName,
Attributes attributes) throws SAXException
{
stack.push(qName);
for(int i = 0; i < attributes.getLength(); i++)
{
String attrName = attributes.getQName(i);
String attrValue = attributes.getValue(i);
System.out.println(attrName + "=" + attrValue);
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException
{
String tag = stack.peek();
if("NAME".equals(tag)){
name = new String(ch, start,length);
}
else if("ADDRESS".equals(tag)){
address = new String(ch, start, length);
}
else if("EMAIL".equals(tag)){
email = new String(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String
qName)
throws SAXException
{
stack.pop(); //表示该元素已经解析完毕,需要从栈中弹出
if("PERSON".equals(qName))
{
System.out.println("name:" + name);
System.out.println("address:" + address);
System.out.println("email:" + email);
System.out.println();
}
}
3jdom解析

JDOM是一种使用 XML 的独特 Java 工具包,用于快速开发 XML 应用程序。它的设计包含 Java 语言的语法乃至语义。JDOM是一个开源项目,它基于树型结构,利用纯JAVA

的技术对XML文档实现解析、生成、序列化以及多种操作。(http://jdom.org)

JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念等),把SAX和DOM的功能有效地结合起来.JDOM是用Java语言读、写、操作

XML的新API函数。在直接、简单和高效的前提下,这些API函数被最大限度的优化。

JDOM 主要用来弥补DOM及SAX在实际应用当中的不足之处。这些不足之处主要在于SAX没有文档修改、随机访问以及输出的功能,而对于DOM来说,JAVA程序员在使用时来

用起来比较麻烦。

DOM的缺点主要是由于DOM是一个接口定义语言(IDL),它的任务是在不同语言实现中的一个最低的通用标准,并不是为JAVA特别设计的。

3.1JDOM的好处

1)在 JDOM 中,XML 元素就是 Element 的实例,XML 属性就是 Attribute 的实例,XML 文档本身就是 Document 的实例

2)JDOM 是 Java 平台专用的。只要有可能,API 都使用 Java 语言的内建String 支持,因此文本值也适用于 String 。它还可利用 Java 2 平台的类集,如 List 和Iterator

,给程序员提供了一个丰富的并且和Java 语言类似的环境。

3)没有层次性。在 JDOM 中,XML 元素就是 Element 的实例,XML 属性就是Attribute 的实例,XML文档本身就是 Document 的实例。由于在XML 中所有这些都

代表了不同的概念,因此它们总是作为自己的类型被引用,而不是作为一个含糊的“结点”。

4)类驱动。因为 JDOM 对象就是像 Document 、Element 和 Attribute 这些类的直接实例,因此创建一个新 JDOM 对象就如在 Java 语言中使用 new 操作符一样容易。它

还意味着不需要进行工厂化接口配置 -- JDOM 的使用是比较直接。
例:(创建一个xml)

public static void main(String[] args) throws Exception {
Document document = new Document();
Element root = new Element("person");
document.addContent(root);
Comment comment = new Comment("This is my comments");
root.addContent(comment);
Element e = new Element("user");
e.setAttribute("id", "1");
root.addContent(e);
Element e2 = new Element("address");
Attribute attr = new Attribute("country", "cn");
e2.setAttribute(attr);
e.addContent(e2);
e2.addContent(new Element("city").setAttribute("test1",
"value1")
.setAttribute("test2", "中文").setAttribute("test3",
"value3")
.setText("text content"));
Format format = Format.getPrettyFormat();
format.setIndent(" ");// 设置间隔
format.setEncoding("gbk");// 设置字符集
XMLOutputter out = new XMLOutputter(format);
out.output(document, new FileWriter("test.xml"));
}
例:(读写上述创建的xml)

public static void main(String[] args) throws Exception {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File("test.xml"));
Element element = doc.getRootElement();
System.out.println(element.getName());// 输出根元素
Element user = element.getChild("user");
List list = user.getAttributes();
for (int i = 0; i < list.size(); i++) {
// 获得该节点的所有的属性
Attribute attr = (Attribute) list.get(i);
String attrName = attr.getName();
String attrValue = attr.getValue();
System.out.println(attrName + "=" + attrValue);
}
user.removeChild("address");// 删除address节点
XMLOutputter out = new
XMLOutputter(Format.getPrettyFormat().setIndent(
" "));
out.output(doc, new FileOutputStream("test2.xml"));
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值