现在的位置: 首页 > 综合 > 正文

java中xml的三种解析方式

2013年10月29日 ⁄ 综合 ⁄ 共 4277字 ⁄ 字号 评论关闭

我们程序拿到了xml文档,是不是有点手足无措,下面我们一起看一看如何在程序中去解析一个xml文档:

1:dom解析

这种解析方式是W3C官方的解析方式,它将文档整个载入到内存中,然后在内存中直接操作文档,这样有俩优点:1,读取效率比从硬盘上读快很多,2,整个文档都在内存里,所以增删改查很方便。

增删改查操作流程:
第一步都是一样的:加载xml文件,得到document对象:

a:创建一个xml文档解析器工厂对象   b:通过工厂创建一个xml文档解析器对象  c:通过解析器对象解析一个文件对象得到Document对象

增加节点:
创建一个标签,然后给标签添加元素,再将元素添加到document中,最后将document中的内容写入到文件里

删除节点:
删除节点比较麻烦,接下来的步骤有:取出所有element,进行遍历,找到符合条件的节点,然后取得这个节点的父节点,对这个父节点进行删除子节点操作。再然后建立一个转移工厂,将内存中数据重新写入到文件中去

修改节点:
找到符合条件的节点,将节点的内容进行修改,再将修改后的内容从内存写到文件中

查找节点:
接下来的步骤是:遍历找到有这个元素的节点,将节点的信息输出

贴个栗子,方便大家研究吧:

// 删除某一个节点: 删除id为008的用户信息
/*
* <users>
<user id="007">
<name>王五</name>
<password>888</password>
</user>
<user id="008">
<name>张三</name>
<password>123</password>
</user>
</users>
*/
@Test
public void testDeleteUserById() throws Exception {
Document document = getDocument();
NodeList list = document.getElementsByTagName("user");
for(int i=0;i<list.getLength();i++) {
Element userEle = (Element) list.item(i);
String id = userEle.getAttribute("id");
if("008".equals(id)) {
//得到父标签,用父标签删除自己
userEle.getParentNode().removeChild(userEle);

//将document对象中的数据保存到user.xml
saveDocument(document);
System.out.println("删除成功啦!");
return;
}
}
System.out.println("没有找到对应的user");
}

2:然后是SAX解析

SAX解析虽然非官方,但是运用非常广泛:

sax读取xml的时候是一行一行的载入,我们parse的时候,它会自动的去从头到尾的去读取文件。使用sax去操作一个xml文件的时候最重要的注意点是我们需要知道在哪一步添加操作代码拿老师的读取第二本书作者名字作为栗子,那我们知道条件,首先我们要知道什么时到第二本书了(在dom模式下就不需要这么繁琐了,我们可以直接在nodelist中找到下标为1的那个元素,取出作者就OK了),那我们就在读取  书这个元素结束的时候对我们的标识码进行加一操作,这样哪怕是要找第100本书,我们都不怕了,第二需要找出坐着这个元素,那我们就在作者的element的开始标签那做判断,是否符合条件。

综上所述:使用sax不像使用dom那么来的方便,我们需要使用各种标签以及缓存变量来记录和标识我们所需要使用的那些东西,但是非常节省内存,在内存比较紧张或者文件比较大的情况下我们使用这种方式进行解析

public class SaxDemo1 {

public static void main(String[] args) throws Exception {
// 得到SAX解析器
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
// 得到读取器
XMLReader reader = parser.getXMLReader();
// 注册事件处理器
reader.setContentHandler(new ContentHandler1());
// 读取XML文档
reader.parse("src/books.xml");
}
}

class ContentHandler1 extends DefaultContentHandler {
@Override
public void startDocument() throws SAXException {
System.out.println("文档的开始");
}

@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.println("元素的开始"+qName);
}

public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println(new String(ch,start,length));
}

public void endElement(String uri, String localName, String qName)
throws SAXException {
System.out.println("元素的结束"+qName);
}

public void endDocument() throws SAXException {
System.out.println("文档的结束");
}
}

这里使用了一个适配器,适配器就自己配一下了,不展开。

3:就是pull解析了,这个在android上广泛应用

我们都知道前面的两种方式的局限性和优点了,那么pull解析和sax如出一辙,只是我们需要手动的去推着它去往前运行。对于上面的操作本人原来有一点点小小的疑问,既然我们还是要将所有的xml文件的节点全部放到内存里,为什么就要有一个pull的解析呢,后来想通了,有时候我们不必要把整个文件都放到内存里,我们中间可以对它进行一定的筛选,然后载入到内存中去,这样虽然浪费了一点cpu但是换来了很多的内存空间,而且我们在不需要读完一个文件的情况下,我们可以在使用后直接return出来,方便很多。

放一个栗子吧:

public class PullDemo1 {

public static void main(String[] args) throws Exception {
//得到pull解析器:XMLPullParser
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
//传入要读取的XML文件
parser.setInput(new FileInputStream("src/books.xml"),"UTF-8");
//读第一部分:得到读到的当前部分的类型   int
int eventType = parser.getEventType();
//判断是不是你想要的类型:
while(eventType!=XmlPullParser.END_DOCUMENT){
if(eventType==XmlPullParser.START_DOCUMENT)
System.out.println("读到了文档的开始");
if(eventType==XmlPullParser.START_TAG)
System.out.println("读到了元素的开始");
if(eventType==XmlPullParser.TEXT)
System.out.println("读到了主体内容");
if(eventType==XmlPullParser.END_TAG)
System.out.println("读到了元素的结束");
//游标下移
eventType = parser.next();
}
}
}

不过这个要加入pull的包哦

最后有一个dom4j的解析,这种解析是将dom和sax做了一个相当于整合,很方便使用

Dom4J解析提供很简单的操作,例如可以直接new一个SAXReader等等,它可以像dom一样去实现增删改查(通过直接指定一个元素,类似于 List bookChildrens = root.elements("书");//所有的书孩子   这样的操作,为我们提供了很多便利。而且直接给我们提供了增删改查接口,使用起来非常方便)

直接上一个栗子:

// 1、得到某个具体的节点内容
//取第2本书的作者
@Test  
public void test1() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/books.xml");
Element root = document.getRootElement();
//按层次获取指定的元素
List bookChildrens = root.elements("书");//所有的书孩子
Element book2 = (Element) bookChildrens.get(1);//第2本书

Element book2Author = book2.element("作者");
String author = book2Author.getText();//作者的主体内容
}

是不是方便了很多??

没有最方便,只有更方便,xPATH的引入让我们的操作如虎添翼:

同样上面的栗子我们用xPATH来尝试下:

@Test  //Xpath
public void test11() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/books.xml");
//按层次获取指定的元素
String xpath = "//书[2]/作者";
Node node = document.selectSingleNode(xpath);
}

呵呵,xPATH这里就不展开了,有时间再贴一篇日志吧

注:当得知张孝祥老师已然辞世,一种莫名的茫然和忧伤,请接受一个菜鸟晚到的膜拜...

抱歉!评论已关闭.