2012年3月20日星期二

利用Dom4J的SAXReader解析大文件 - - ITeye技术网站

利用Dom4J的SAXReader解析大文件 - - ITeye技术网站

今天用到了对内容量很大的XML文件的解析,顺便记录一下。 



      关于XML的解析技术网上有很多文章,不再详述。 主要的方式有JDK自带的JAXP(Java API For XML Parser)、JDom、Dom4j等。其中Dom4J是相当灵活的,很多开源框架都基于Dom4J来做XML解析。 

      底层的解析器主要有两种: DOM、SAX。 其中DOM作为树型结构将文本装载到内存中,适合文本内容比较小的;SAX则按照流的方式扫描,事件触发的方式供你处理,比如遇到某个结点的开始符,结束符,大文本不能一次性装载到内存中,就应该采用SAX方式。 



      DOM4J利用SAXReader类来读取文件,然后为SAXReader对象设置元素处理解析器ElementHandler,有doStart和doEnd两个方法,分别在遇到元素的开始符号和结束符号时候触发。只需在相应的方法内实现自己的业务逻辑即可。 



例子:  XML文件结构如下: 

view plaincopy to clipboardprint?<?xml version="1.0" encoding="GB2312"?>  
<TESTINFO version="1.0">  
    <UPDATEINFO>  
        <PARAM_TIMESTAMP>2010-12-22 09:54:09</PARAM_TIMESTAMP>  
        <CITYINFO_LIST>  
            <CITYINFO City="591" Name="XYZ" No="334" />  
            <CITYINFO City="591" Name="BJD" No="335" />  
            <CITYINFO City="591" Name="UUS" No="390" />  
        </CITYINFO_LIST>  
    </UPDATEINFO>  
</TESTINFO>  
<?xml version="1.0" encoding="GB2312"?> 
<TESTINFO version="1.0"> 
<UPDATEINFO> 
<PARAM_TIMESTAMP>2010-12-22 09:54:09</PARAM_TIMESTAMP> 
<CITYINFO_LIST> 
<CITYINFO City="591" Name="XYZ" No="334" /> 
<CITYINFO City="591" Name="BJD" No="335" /> 
<CITYINFO City="591" Name="UUS" No="390" /> 
</CITYINFO_LIST> 
</UPDATEINFO> 
</TESTINFO> 




其中CITYINFO可能是个很大的列表。 完整的程序代码如下: 



view plaincopy to clipboardprint?package com.atu.xmltest;  
  
import java.io.InputStream;  
  
import org.dom4j.DocumentException;  
import org.dom4j.Element;  
import org.dom4j.ElementHandler;  
import org.dom4j.ElementPath;  
import org.dom4j.io.SAXReader;  
  
public class MySaxHandler implements ElementHandler {  
      
    SAXReader reader;  
    public MySaxHandler() {  
        // test.xml文件跟类放在同一目录下   
        try {  
            InputStream is = MySaxHandler.class.getResourceAsStream("test.xml");   
            reader = new SAXReader();  
            reader.setDefaultHandler(this);  
            reader.read(is);  
        } catch (DocumentException e) {  
            e.printStackTrace();  
        }  
    }  
    @Override  
    public void onEnd(ElementPath ep) {  
        Element e = ep.getCurrent(); //获得当前节点   
        if(e.getName().equals("PARAM_TIMESTAMP"))  
            System.out.println("解析到时间:"+e.getText());  
        else if(e.getName().equals("CITYINFO")){  
            System.out.printf("解析到CITYINFO,属性值为:%s,%s,%s/n", e  
                    .attributeValue("City"), e.attributeValue("Name"), e  
                    .attributeValue("No"));  
        }  
        e.detach(); //记得从内存中移去   
    }  
  
    @Override  
    public void onStart(ElementPath ep) {  
    }  
      
    public static void main(String[] args){  
        new MySaxHandler();  
    }  
  
}  
package com.atu.xmltest; 

import java.io.InputStream; 

import org.dom4j.DocumentException; 
import org.dom4j.Element; 
import org.dom4j.ElementHandler; 
import org.dom4j.ElementPath; 
import org.dom4j.io.SAXReader; 

public class MySaxHandler implements ElementHandler { 

SAXReader reader; 
public MySaxHandler() { 
// test.xml文件跟类放在同一目录下 
try { 
InputStream is = MySaxHandler.class.getResourceAsStream("test.xml"); 
reader = new SAXReader(); 
reader.setDefaultHandler(this); 
reader.read(is); 
} catch (DocumentException e) { 
e.printStackTrace(); 


@Override 
public void onEnd(ElementPath ep) { 
Element e = ep.getCurrent(); //获得当前节点 
if(e.getName().equals("PARAM_TIMESTAMP")) 
System.out.println("解析到时间:"+e.getText()); 
else if(e.getName().equals("CITYINFO")){ 
System.out.printf("解析到CITYINFO,属性值为:%s,%s,%s/n", e 
.attributeValue("City"), e.attributeValue("Name"), e 
.attributeValue("No")); 

e.detach(); //记得从内存中移去 


@Override 
public void onStart(ElementPath ep) { 


public static void main(String[] args){ 
new MySaxHandler(); 








运行结果: 



解析到时间:2010-12-22 09:54:09 
解析到CITYINFO,属性值为:591,XYZ,334 
解析到CITYINFO,属性值为:592,BJD,335 
解析到CITYINFO,属性值为:593,UUS,390 

没有评论: