您的位置:首页 > 其它

解析xml文档总结(一)

2014-05-03 23:31 141 查看
开发javaWEB项目,经常都要遇到xml文件,我们只要在xml配置项目的一些属性,那么项目就可以按我们所想的运作了。那么xml文件的数据是如何转化为系统可以识别的信息呢?这就需要解析xml文件了。

要解析xml文件就要有xml解析器,比较著名的有Apache的Xerces,微软的MSXML,Oracle的XMLParser等。如果系统要更换解析器就要修改源代码,那也太不人道了。幸运的事,这些解析器大都支持两套API:DOM和SAX,因此,我们针对DOM接口或SAX接口编程可以极大简化更改解析器时代码的修改。

另外,Oracle制定的JAXP规范在解析器之上提供了一层抽象,使我们可以独立于厂商API进行编程。在JavaSE中,JAXP的开发包由javax.xml,org.w3c.dom和org.xml.sax三个包组成。其中javax.xml.parsers包中定义了几个工厂方法用于加载DOM或SAX的实现类。其实现类可以很方便地更换,只要修改制定文件的一些配置即可。这个后面细讲。

因此针对JAXP编程可以随意更换解析器而不用修改任何的源代码。

以下具体说说DOM和SAX。

先说DOM吧。DOM把xml文档处理成一棵节点树,xml的元素,属性,文本,注释,数据段等在DOM中都有对应的类。且看类图:



有了这张图,再看后面的代码应该能容易一些。给出一个例子吧:

books.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<books>
<book name="java">
<author>Bruce</author>
<price>100</price>
</book>
<book name="c++">
<author>Dinail</author>
<price>80</price>
</book>
</books>


代码如下:

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class SimpleTest {

public void test(){
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();//获得解析器实现类,获取方法后面讲
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Document d = db.parse(new File("books.xml"));
NodeList nl = d.getElementsByTagName("book");//获得所有的book节点
for(int i = 0;i < nl.getLength();i++){
Element e = (Element)nl.item(i);//将book节点转换成元素
String bookname = nl.item(i).getAttributes().item(0).getNodeValue();//获得book节点的属性列表,然后是第一个属性并得到其值
Node n1 = e.getElementsByTagName("author").item(0);
Node n2 = e.getElementsByTagName("price").item(0);
String author = n1.getFirstChild().getNodeValue();
String price = n2.getLastChild().getNodeValue();
System.out.println("bookname:"+bookname+"\n\tauthor:"+author+"\n\tprice:"+price);
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void main(String[] args) {
new SimpleTest().test();
}

}


应该注意的是,<book>与<author>之间有一个text节点,类似的,还有其他一些空白节点。其他的注释已经讲的清楚了,以下是输出:

bookname:java
author:Bruce
price:100
bookname:c++
author:Dinail
price:80


ok,回到上面的一个问题,如果要换解析器怎么办呢?或者说DocumentBuilderFactory.newInstance()是怎么找到实现类的呢?且听我细细道来。

关键之处在于javax.xml.parsers.DocumentBuilderFactory这个系统属性的设置。

可以通过System.setProperty("javax.xml.parsers.DocumentBuilderFactory","org.apache.parsers.jaxp.DocumentBuilderFactoryImp")

可以在执行时指定:java -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.parsers.jaxp.DocumentBuilderFactoryImp

可以在jre/lib下添加jaxp.properties文件并添加一条记录:javax.xml.parsers.DocumentBuilderFactory=org.apache.parsers.jaxp.DocumentBuilderFactoryImp

如果都没找到,那就使用JDK自带的解析器了,在com\sun\org\apache\xerces\internal下

以下是SAX解析xml的一个例子,xml文件用上面那个:

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

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

public class SimpleTest {

public void test(){
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
SAXParser sp = spf.newSAXParser();
sp.parse(new File("books.xml"),new SAXHandler());
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void main(String[] args) {
// TODO Auto-generated method stub
new SimpleTest().test();
}

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

@Override
public void startElement(String uri,String localName,String qName,Attributes attr) throws SAXException{
System.out.print("<"+qName);
int length = attr.getLength();
for(int i = 0;i < length;i++){
System.out.print(" "+attr.getQName(i)+"="+attr.getValue(i));
}
System.out.print(">");
}

@Override
public void characters(char[] buf,int start,int length) throws SAXException{
System.out.print(new String(buf,start,length));
}

@Override
public void endElement(String uri,String localName,String qName) throws SAXException{
System.out.print("</"+qName+">");
}
}


ok,可以看出,SAX使用基于事件的机制,解析xml文档时要指定处理类,处理类指定遇到开始元素怎么办,遇到文本怎么办,遇到结束怎么办等等,详细资料可以查阅相关文档。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: