加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

DBLP文献管理系统(二)XML的解析

(2017-07-25 12:49:48)
标签:

数据处理

大作业

l  问题描述

拿到dblp文件后,我感觉非常苦恼,由于文件本身较大(约为1.8GB),且不说使用何种存储方式来处理这份庞然大物,如何高效解析它,让程序准确无误读出其中的内容也是一项不小的挑战。

 

l  内容分析

通过简单浏览dblp.xml的内容(无法直接用记事本打开,这里推荐大家使用cmd命令行的more命令来查询),我们可以发现dblp中的数据组织形式基本形式如下:

 

<article mdate="2006-03-06" key="journals/interactions/ArnowitzD05p">

<author>Jonathan Arnowitz</author>

<author>Elizabeth Dykstra-Erickson</author>

<title>Hello, goodbye in the line of HCI.</title>

<pages>5-9</pages>

<year>2005</year>

<volume>12</volume>

<journal>Interactions</journal>

<number>5</number>

<ee>http://doi.acm.org/10.1145/1082369.1082373</ee>

<url>db/journals/interactions/interactions12.html#ArnowitzD05p</url> 

</article>

 

当然,外面还有一些注释标签和首级标签:

 

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE dblp SYSTEM "dblp.dtd">

<dblp>

</dblp>

可以知道,dblp中数据是以xml标签的形式,并在一级目录<article></article>下,加入各种次级标签<author><title><pages><year>等等。

 

这里对几种变形情况进行说明:

1. 一级目录有可能不是<article>,而有可能是:<inproceedings><proceedings><book><incollection><phdthesis><mastersthesis><www>等等(这些标签在较靠后的位置出现的频率很高)

2. 作者<author>可以有多个(具体最多几个没统计过读者可以自己写个小的程序测试一下)

3. 次级标签<author><title>固定出现,相当于每篇文章的固有属性。

4.次级标签<pages><year><url>等经常出现,但也可能不出现,或者出现的顺序是打乱的,也有可能会有没见过<note><cite>等标签,总之一句话,乱七八糟。

如何解析整个xml文件,并高效处理其中的数据使其支持查询和统计操作是需要精心设计的。

(补充说明:由于DBLP文献集是官方性的文件,而且本程序主要是体现大良数据处理的原理,所以在这里增删改功能意义不大,没有加入)

 

l  XML解析

百度一下,你就会发现其实对于xml文件的解析方法是非常多的,大到使用封装性极强的库,小到使用寥寥几行代码,原理、效率、适用场景都是不一样的,这里我们列举两种最主流的解析原理来分析DBLP文献管理系统的需求:

 

一、DOM解析

文档对象模型(Document Object Model,简称DOM,是以层次结构组织的节点或信息片断的集合。具体的组织形式可能会因为使用的方法或库不同稍有变化,但从最本质和通俗的角度来说,DOM解析它的本质就是将xml完全读取,然后构造出一颗树(其中的根节点代表一级标签,叶子节点代表次级标签等),以便于通过一系列接口对xml文件进行操作。

这样的解析形式,被广泛运用在HTML中,当然xml同样可以,但是由于树结构和电脑本身的内存限制,要求完全读取,就必然要求文件不能太大。

笔者就尝试过用tinyxml(一个轻量级的DOM解析库)来处理DBLP文件,很快就发现,完全不现实,只好作罢。(听说mmap的形式可以弥补内存不足的缺陷,这里不做展开,欢迎读者自己尝试)

 

二、SAX解析

模型(也称为流解析),全称Simple API for XML它是一种XML解析的替代方法。SAX不同于DOM解析,它逐行扫描文档,一边扫描一边解析。由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势(节选自百度百科)。

利用SAX解析,我们就需要定义自己的解析方式。

笔者是用C++语言来开发的,对于结点的解析可以通过如下方法来实现:

 

getline(indblp, tempstr);//读取一行,存入tempstr

       if (tempstr.find("<author>") != string::npos) {//找到了author结点

           size_t startPos = tempstr.find_first_of(">");//找到第一个>

           size_t endPos = tempstr.find_last_of("<");//找到最后一个<

           coauthor_tree.insert(tempstr.substr(startPos +1, endPos - (startPos + 1)));}//获得内容

 

由于结点形如:<author>内容</author>,所以在第一个>与最后一个<之间的,必然就是我们想要的内容,这里我们使用子串tempstr.substr()函数,截取内容,并将内容插入合作树coauthor_tree(自己定义的一个对象,在后文中会加以说明)中,实现了我们想要的解析并操作功能。

 

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有