admin 管理员组文章数量: 1086019
2024年4月20日发(作者:减速机滑块联轴器)
< ≮ 曼Yl墨 c! 里 缠塞
解析大数据量XML文件的实现
◆张二松缪红萍宋梦馨
摘要:信息系统在解析大数据量的xML文件时,容易发生内存溢
出问题。本文详细介绍了如何通过SAX方式解析大数据量的XML文件。
SAX是一种消耗内存较小的解析方式。它能有效解决由于大量消耗内存
而导致的内存溢出问题。
关键词:SAX;dom4j;大数据量;内存溢出
<?xml version=”1.0”encoding=”gb23 12”?>
一
、
引言
<root>
XML文件被广泛应用于信息系统之间传递数据。
<application name=”sale”>
信息系统接收到xML文件,在进行解析后才能加载数
<seller name=”SuperMarketA.xml’’>
据。当XML文件中的数据量较小时,多种解析方式都
<product name="coffee”>
能够完成解析XML文件。然而,随着XML文件中的数
<attribute>price</attribute>
据量的不断增大,有些解析方式消耗的内存也越来越
<attribute>brand</attribute>
大,由于超出了内存的处理能力,最终会出现内存溢出
<attribute>weight</attribute>
问题。在解析XML文件的各种方式中,SAX方式在解
</product>
析大数据量的XML文件上具有优势。它不需要将整个
<product name=”milk”saveasname=”freshmilk”>
XML文件加载到内存里面,占用的内存比较少,因此
<attribute>price</attribute>
它适合解析大数据量的XML文件。
<attribute>brand</attribute>
本文以解析包含了大量商品信息的XML文件(包括
<attribute>specifications</attribute>
SuperMarketA.xml、SuperMarketB.xml、SuperMarketC.
</product>
xm1)为例,首先建立这& ̄XML文件的配置文件(config.
xm1),然后使用SAX方式解析这些XML文件。
</seller>
<seller name=”SuperMarketB.xml”>
二、创建XML配置文件
在实际应用中,XML文件里面的标记信息,有时
</seller>
会因业务需要而做调整。当这些XML文件中的标记变
<seller/lame=”SuperMarketC.xml’’>
更时,解析XML文件的程序源文件也需要做相应的修
改,因此,程序源文件需要重新编译才能使用。为了
</seller>
防止修改程序源文件,建立一个配置文件,也就是把
</application>
XML文件中的所有标记全部存储到一个XMLi ̄置文
</root>
件中。在程序源文件中,不再写入XML文件的标记信
息,而是当需要标记信息时直接从配置文件中获取。这
config.xml配置文件的数据量只有几十k大小,可
样,当标记变更时,只需要在配置文件中进行修改,而
以不用考虑内存消耗问题。本文使用dom4j方式解析
不用修改程序源文件。
config.xml文件,它具有简单易用、访问灵活等特点。
XML配置文件除了可以进行灵活的扩展变化,还 首先创建类文件Dom4jParse.java,然后在类
可以反映清晰的层级嵌套关系。下面的XML配置文件
中建立两个方法:getAttribute0和getElement()。其
(config.xm1)反映了四个层级关系:销售、销售公司、产 中,getAttribute0方法用于获取元素的name属性值
品、产品的属性。config.xmllf?,置文件如下: (如:application元素的name属性值是“sale”),
36 信息系统工程f 2012.9.20
getElement()方法用于获取元素内容(如:第一个
attirbute元素的内容是“price”)。
实 ̄getAttribute0方法的程序思路如下:
// ̄s]建SAXReader ̄析器实例
SAXReader reader:new SAXReader();
//读取XML文件
Document doc=reader.read(new File(”config.
xml”));
//获取文档的根节点
Node root=doc.selectSingleNode(”/root”);
//获取所有的seller: ̄素
List list=root.selectNodes(”/root/application[@
name=’sale’]/seller”);
∥获取seller ̄素的name属性值
for(0bjectobject:list){
Element element=(Element)object;
element.attributeValue(”name”);
}
实现getElement0方法的程序和实现getAttribute0方
法的程序类似。使用方法getText0替换上面程序代码中
的方法attributeValue0,就能实现getElement0方法。
三、解析大数据量XML文件
下面是存储了大量商品信息的SuperMarketA.xm1。
<?xml version=”1.0”encoding=”gb23 1 2”?>
<SuperMarketA>
<coffee>
<price>69元</price>
<brand>雀巢96+4杯咖啡促销装</brand>
<weight>1 300g</weight>
</coffee>
<coffee>
<price>36.9兀</price>
<brand>麦斯威尔条装咖啡特浓</brand>
<weight>494g</weight>
</coffee>
<milk>
<price>29.9元</price>
<brnad>蒙牛纯牛奶(整箱)</brnad>
<speciifcations>485ml 8袋</speciifcations>
sYs .! 旦 塞壁 >
</milk>
<milk>
<price>33元</price>
<brand>光明利乐枕优+纯牛奶</brand>
<speciifcations>23 1ml 12袋</speciifcations>
</milk>
<SuperMarketA>
以解析SuperMarketA.xml文件为例,信息系统在解
析XML文件时,需要按照商品类别,把不同的商品信
息分别存储到不同的文件里面。也就是,当第一次解
析到商品标记(如:<coffee>、<milk>等)时,创建以
商品标记为名称的文本文件(如:coffee.txt、milk.txt
等),然后把解析出来的商品信息(如: “69元”、
“雀巢96+4杯咖啡促销装”、“1300g”等)存储到相
应的文本文件中。
本文采用SAX方式解析大数据量的XML文件。
SAX方式的工作原理是:解析器顺序扫描XML文件,
当扫描到一个标记时,就会产生一个事件,由事件处理
器调用相应的方法进行处理,然后解析器继续进行同样
的扫描,直 ̄IJXML文件结束。因此,SAX方式不会占
用大量内存,不会造成内存溢出问题。
SAX方式解析XML文件的过程,通常需要经过
5个步骤:startDocument,startElement,characters,
endElement,endDocument。在各个步骤中,可以进行
逻辑判断、获取元素内容、处理元素内容、存储元素内
容、输出元素内容等操作。以下是在SAX解析类中使用
到的5个方法,它们分别对应着这5个步骤。
(1)startDocument()方法:开始处理文档。
(2)startElement(String uri,String localName,
String qName,Attributes atts)方法:开始处理元素。需
要判断参数qName是哪个层级的开始标记(是<coffee>
层级的标记?还是<price>层级的标记?),以确定什
么时候开始获取元素内容。另外,需要创建输出文件
(如:coffee.txt、milk.txt等)。
(3)characters(char[1 ch,int start,int length)方
法:获取元素内容。如果qName是<price>层级的开始标
记,就获取元素的内容(如:“69元”等)。
(4)endElement(String uri,String localName,
String qName)方法:结束处理元素。需要对获取到的
元素内容进行处理(如:过滤某些内容等),并进行临
时存储,最后将它们输出到对应的文件中(如:coffee.
txt、milk.txt等)。这样,内存中存储的元素内容,就
信息系统工程}2012.9.20 37
< SYS PRACTICE 系统实践
会不断地输出到存储设备的文件中,因此不会造成内存
溢出问题。
{
public static void main(String[]args)throws Exception
(5)endDocument0方法:结束处理文档。需要进
行一些必要的处理(如:关闭流等)。
SAX: ̄式解析大数据量XML文件的程序思路如下:
//通过继承DefaultHandler ̄来继承SAX事件处理方
1)通过a曙s参数,传递需要解析的Ⅺ血文件的路径。
2)通过Dom4jParse.java解析配置文件config.xml,
获得需要解析的XML文件名(如:SuperMarketA.xml、
SuperMarketB.xml等)。
3)使用SAX方式逐一解析XML文件(以解析
法。
public class SAXParse extends DefaultHandler{
,/开始解析XML文档。
public void startDocument()throws SAXException{}
//开始解析元素。
public void startElement(String uri,String
localName,String qName,Attributes atts)throws
SAXException{
1)判断qName是否为<coffee> ̄级的开始标记。
如果是,则进一步判断<coffee>是否是第一次出现。如
果是,则创建coffee.txt输出文件。
2) ̄lJ断qName是否为<price>层级的开始标记。
如果是,则进入characters方法。
}
//获取元素内容。
public void characters(char[】ch,int start,int length)
{
1) ̄lJ断当前是否在解析<price>层级的标记。如
果是,则获取元素的内容。
}
//元素解析完毕。
public void endElement(String uri,String
localName,String qName)throws SAXException{
1)]lJ断qName是否为<price>层级的结束标记。
如果是,则对元素内容进行某些处理(如:过滤空格、
字符转换等),然后临时存储元素内容。
2)判断qName是否为<coffee>层级的结束标记。
如果是,则将临时存储的所有元素内容输出到相应的
文件中(如果是</coffee>,则输出 ̄lJcoffee.txt。如果是</
milk>,则输出到milk,txt)。
)
//文档解析完毕。
public void endDocument()throws SAXException{
11关闭流。
}
//主函数,执行SAXParse解析程序的人口。
38 信息系统工程l 2012.9.20
SuperMarketA.xml为例)。
//创建SAX解析器工厂实例。
SAXParserFactory spf=SAXParserFactory.
newlnstance0;
//使用SAX解析器工厂创建解析器实例。
SAXParser sp=spf.newSAXParser();
//paraml:输出文件的路径。
//param2:config.xml@的所有<product>的name属
性值和对应的<attribute>内容。
SAXParse handler=new SAXParse(param l,
param2);
//使用SAXParser ̄析器解析XML文件。
sp.parse(new File(”SuperMarketA.xml”),handler);
)
}
上面的SAX解析程序将XML文件的解析结果存储
到了文本文件中。如果对解析结果有不同的需求,那么
可以在SAX解析程序上进行相应的调整。
四、结束语
本文通过创建SAX解析程序,实现了解析大数据量
的XML文件,最终解决了内存溢出问题。此外,本文
还引入了配置文件,当XML文件中的标记有变更时,
只需要更改配置文件中的标记,不会影响到SAX解析程
序源文件。 髑
参考文献
[1】张太彪,曾文华,陈志伟.大型XML文档解析技术的应用与研究
[7】.厦门大学学报:自然科学版,2009,5,48(3):338-341.
【2】张迪,朱敏,张凌立.基于sAx的xML解析与应用Ⅱ】.计算机与数
字工程,2008,225(7):103—106.
[31.- ̄炎.基ff-SAX ̄XML解析异常处理方法Ⅲ.陕西科技大学学
报,2009,10,27(5):106—109.
[4]刘雨潇.基于SAX的XML数据解析技术分析研究卟现代电子
技术,2010,323(12):55—56,65.
(作者单位:张二松。中国石油勘探开发研究院西
北分院;缪红萍、宋梦馨。中国石油勘探开发研究院
计算机应用技术研究所)
版权声明:本文标题:解析大数据量XML文件的实现 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1713564341a640969.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论