虽然python解析xml的库很多,但是,由于lxml在底层是用C语言实现的,所以lxml在速度上有明显优势。除了速度上的优势,lxml在使用方面,易用性也非常好。这里将以下面的xml数据为例,介绍lxml的简单使用。

例子:dblp.xml(dblp数据的片段)<?xml version='1.0' encoding='utf-8'?>Stefano BellucciSergio FerraraAlessio MarraniArmen YeranyanES2: A cloud data storage system for supporting both OLTP and OLAP.507-555200810Entropy4http://dx.doi.org/10.3390/e10040507db/journals/entropy/entropy10.html#BellucciFMY08Kevin H. KnuthEntropy Best Paper Award 2013.698-699201315Entropy2http://dx.doi.org/10.3390/e15020698db/journals/entropy/entropy15.html#Knuth13

1、将xml解析为树结构,并得到该树的根。

为了将xml解析为树结构,并得到该树的根,要进行如下的操作:

1 #!/usr/bin/python

2 #-*-coding:utf-8-*-

3 from lxml import etree#导入lxml库

4 tree = etree.parse("dblp.xml")#将xml解析为树结构

5 root = tree.getroot()#获得该树的树根

另外,如果xml数据中出现了关于dtd的声明(如下面的例子),那样的话,必须在使用lxml解析xml的时候,进行相应的声明。

xml文件中含有dtd声明的例子:<?xml version="1.0" encoding="ISO-8859-1"?>

E. F. Codd

Further Normalization of the Data Base Relational Model.

IBM Research Report, San Jose, California

RJ909

August

1971

hadoop@hadoop:~/20130722dblpxml$ head -15 dblp.xml<?xml version="1.0" encoding="ISO-8859-1"?>

E. F. Codd

Further Normalization of the Data Base Relational Model.

IBM Research Report, San Jose, California

RJ909

August

1971

ibmTR/rj909.pdf

db/labs/ibm/RJ909.html

这时候,要想将xml数据解析为树结构并得到该树的树根,必须进行如下的操作:

1 #!/usr/bin/python

2 #-*-coding:utf-8-*-

3 from lxml import etree#导入lxml库

4 parser=etree.XMLParser(load_dtd= True)#首先根据dtd得到一个parser(注意dtd文件要放在和xml文件相同的目录)

5 tree = etree.parse("dblp.xml",parser)#用上面得到的parser将xml解析为树结构

6 root = tree.getroot()#获得该树的树根

2、遍历树结构,获得各元素的属性及其子元素。

1 for article in root:#这样便可以遍历根元素的所有子元素(这里是article元素)

2 print "元素名称:",article.tag#用.tag得到该子元素的名称

3 for field in article:#遍历article元素的所有子元素(这里是指article的author,title,volume,year等)

4 print field.tag,":",field.text#同样地,用.tag可以得到元素的名称,而.text可以得到元素的内容

5 mdate=article.get("mdate")#用.get("属性名")可以得到article元素相应属性的值

6 key=article.get("key")7 print "mdate:",mdate8 print "key",key9 print ""#隔行分开不同的article元素

到这里,便可以进行简单的xml数据的解析了。

3、解析xml数据的例子

用下面的代码解析文章开头的名为dblp.xml数据。

1 #!/usr/bin/python

2 #-*-coding:utf-8-*-

3 from lxml import etree#导入lxml库

4 tree = etree.parse("dblp.xml")#将xml解析为树结构

5 root = tree.getroot()#获得该树的树根

6

7 for article in root:#这样便可以遍历根元素的所有子元素(这里是article元素)

8 print "元素名称:",article.tag#用.tag得到该子元素的名称

9 for field in article:#遍历article元素的所有子元素(这里是指article的author,title,volume,year等)

10 print field.tag,":",field.text#同样地,用.tag可以得到元素的名称,而.text可以得到元素的内容

11 mdate=article.get("mdate")#用.get("属性名")可以得到article元素相应属性的值

12 key=article.get("key")13 print "mdate:",mdate14 print "key",key15 print ""#隔行分开不同的article元素

便可以得到输出如下:

1 元素名称: article2 author : Stefano Bellucci3 author : Sergio Ferrara4 author : Alessio Marrani5 author : Armen Yeranyan6 title : ES7 pages : 507-555

8 year : 2008

9 volume : 10

10 journal : Entropy11 number : 4

12 ee : http://dx.doi.org/10.3390/e1004050713 url : db/journals/entropy/entropy10.html#BellucciFMY08

14 mdate: 2012-11-28

15 key: journals/entropy/BellucciFMY0816

17

18 元素名称: article19 author : Kevin H. Knuth20 title : None21 pages : 698-699

22 year : 2013

23 volume : 15

24 journal : Entropy25 number : 2

26 ee : http://dx.doi.org/10.3390/e1502069827 url : db/journals/entropy/entropy15.html#Knuth13

28 mdate: 2013-03-04

29 key: journals/entropy/Knuth13

4、元素既有sub-element,又有text的处理

可以看到在上面的例子中,title元素的内容是不正确的。由于title元素及包含sub-element,又有text内容(如下),这时简单的用.text,并不能正确的得到title元素的内容。上面的例子中,第一个article元素的title只取到了ES,而第二个article元素的title则什么都没取到,None。

1

ES2: A cloud data storage system for supporting both OLTP and OLAP.

2

Entropy Best Paper Award 2013.

由于在这个例子中,子元素比较简单,这里就简单的采取将子元素和text一起打印的方法来解决这一问题。代码如下:

1 #!/usr/bin/python

2 #-*-coding:utf-8-*-

3 from lxml import etree#导入lxml库

4 tree = etree.parse("dblp.xml")#将xml解析为树结构

5 root = tree.getroot()#获得该树的树根

6

7 for article in root:#这样便可以遍历根元素的所有子元素(这里是article元素)

8 print "元素名称:",article.tag#用.tag得到该子元素的名称

9 for field in article:#遍历article元素的所有子元素(这里是指article的author,title,volume,year等)

10 if field.tag=="title":11 print field.tag,":",etree.tostring(field,encoding='utf-8',pretty_print=False)#将元素text连同sub_element一起打印

12 else:13 print field.tag,":",field.text#同样地,用.tag可以得到元素的名称,而.text可以得到元素的内容

14 mdate=article.get("mdate")#用.get("属性名")可以得到article元素相应属性的值

15 key=article.get("key")16 print "mdate:",mdate17 print "key:",key18 print ""#隔行分开不同的article元素

输出如下:

1 元素名称: article2 author : Stefano Bellucci3 author : Sergio Ferrara4 author : Alessio Marrani5 author : Armen Yeranyan6 title :

ES2: A cloud data storage system for supporting both OLTP and OLAP.

7

8 pages : 507-555

9 year : 2008

10 volume : 10

11 journal : Entropy12 number : 4

13 ee : http://dx.doi.org/10.3390/e1004050714 url : db/journals/entropy/entropy10.html#BellucciFMY08

15 mdate: 2012-11-28

16 key: journals/entropy/BellucciFMY0817

18 元素名称: article19 author : Kevin H. Knuth20 title :

Entropy Best Paper Award 2013.

21

22 pages : 698-699

23 year : 2013

24 volume : 15

25 journal : Entropy26 number : 2

27 ee : http://dx.doi.org/10.3390/e1502069828 url : db/journals/entropy/entropy15.html#Knuth13

29 mdate: 2013-03-04

30 key: journals/entropy/Knuth13

当然,不难看出这个问题用这种方法解决比较傻,后面还得将title内容中的tag等不需要部分通过各种字符串的处理将其去掉。最好的方法是能有比较简单的方法,分别获取到一个元素的text和sub_element。下面就讲一下如何实现这个需求:

5、sub_element和text优雅实现版

假设xml文件paper.xml内容如下:

E. F. Codd

ES2: A cloud data storage system for supporting both OLTP and OLAP.

IBM Research Report, San Jose, California

RJ909

August

1971

E. F. Codd

Entropy Best Paper Award 2013.

IBM Research Report, San Jose, California

RJ909

August

1971

ibmTR/rj909.pdf

db/labs/ibm/RJ909.html

可以看到,上面的文件中title字段中,既有子元素,也有嵌套。所以,为了同时取到text和子元素中的text,要单独地为取该字段的text写一个函数,下面是两个具体的实现。

5.1 v1.0

首先考虑的是递归读取各个元素的text,然后将它们拼起来,代码如下:

1 from lxml import etree#paper2.py

2

3 defnode_text(node):4 result = node.text.strip() if node.text else ''

5 for child innode:6 child_text =node_text(child)7 ifchild_text:8 result = result + '%s' % child_text if result elsechild_text9 returnresult10

11 if __name__ == '__main__':12 parser =etree.XMLParser()13 root = etree.parse('paper.xml', parser).getroot()14 for element inroot:15 category =element.tag16 for attribute inelement:17 if attribute.tag == "title":18 print "title:", node_text(attribute)19 else:20 print attribute.tag+":",attribute.text.strip()21 print ""

运行结果如下:

1 $ python paper2.py2 author: E. F. Codd3 title: ES 2

4 journal: IBM Research Report, San Jose, California5 volume: RJ9096 month: August7 year: 1971

8

9 author: E. F. Codd10 title: Entropy11 journal: IBM Research Report, San Jose, California12 volume: RJ90913 month: August14 year: 1971

15 cdrom: ibmTR/rj909.pdf16 ee: db/labs/ibm/RJ909.html

显然,这个方法只能够取到各个子元素的text,然后将它们拼起来,因此,这并不是我们想要的。不知道当时怎么想的,我居然就直接这样用了。现在看来too young, too simple, always naive。

5.2 v2.0

数据都上线快一年了,发现了这个问题。简直不更sb了,这样,我们就要重新写上面去取得xml一个节点中所有text的函数(现在看来,当初将这一个功能写成一个函数还算是比较科学的),下面是现在的方案:

1 from lxml import etree#paper.py

2

3 defnode_text(node):4 result = ""

5 for text innode.itertext():6 result = result +text7 returnresult8

9 if __name__ == '__main__':10 parser =etree.XMLParser()11 root = etree.parse('paper.xml', parser).getroot()12 for element inroot:13 category =element.tag14 for attribute inelement:15 if attribute.tag == "title":16 print "title:", node_text(attribute)17 else:18 print attribute.tag+":",attribute.text.strip()19 print ""

运行之后得到下面的结果:

1 $ python paper.py2 author: E. F. Codd3 title: ES2: A cloud data storage system for supporting both OLTP andOLAP.4 journal: IBM Research Report, San Jose, California5 volume: RJ9096 month: August7 year: 1971

8

9 author: E. F. Codd10 title: Entropy Best Paper Award 2013.11 journal: IBM Research Report, San Jose, California12 volume: RJ90913 month: August14 year: 1971

15 cdrom: ibmTR/rj909.pdf16 ee: db/labs/ibm/RJ909.html

这样,这个问题总算是解决了。下面的问题就是如何将线上的数据更改过来,当然,这又是另外的一个问题了。

0

python lxml_python解析xml之lxml相关推荐

  1. Python语言解析xml文件

    python语言解析xml文件的常用的有两种方式: 通过MiniDom库解析xml文件 通过ElementTree库解析xml文件 MiniDom方式解析xml xml文件以data.xml为例,具体 ...

  2. Python ElementTree 解析 xml文件

    文章目录 一.xml文件结构 二.基础解析 1.加载文档 2.获取根元素 3.根元素的属性 4.遍历其直接子元素 5.通过索引值来访问特定的子元素 查找需要的元素 三.支持通过XPath查找元素 四. ...

  3. Python爬虫解析html:lxml的HtmlElement对象获取和设置inner html

    2019独角兽企业重金招聘Python工程师标准>>> 我在我的个人博客"猿人学网站"和公众号"猿人学Python"上写Python教程,有兴 ...

  4. 如何在Python中解析XML?

    我在包含xml的数据库中有很多行,并且我正在尝试编写一个Python脚本,该脚本将遍历这些行并计算出现特定节点属性的实例数量. 例如,我的树看起来像: <foo><bar>&l ...

  5. Python爬虫解析htm时lxml的HtmlElement对象获取和设置inner html方法

    Python的lxml是一个相当强悍的解析html.XML的模块,最新版本支持的python版本从2.6到3.6,是写爬虫的必备利器.它基于C语言库libxml2 和 libxslt,进行了Pytho ...

  6. 使用python批量解析xml文件并且预处理成json的格式

    基本 文件的xml的格式如下: <?xml version="1.0" encoding="GB2312" ?> <Body><T ...

  7. python 处理xml pandas_在python中解析xml到pandas数据帧

    解决方案中的问题是"元素数据提取"没有正确完成.您在问题中提到的xml嵌套在几个层中.这就是为什么我们需要递归地读取和提取数据.在这种情况下,下面的解决方案应该能满足您的需要.尽管 ...

  8. python ElementTree解析xml

    import xml.etree.ElementTree as ETtree = ET.parse(args.test_file) root = tree.getroot()for m in root ...

  9. Python 中 xpath 语法 与 lxml 库解析 HTML/XML 和 CSS Selector

    The lxml.etree Tutorial :https://lxml.de/tutorial.html python3 解析 xml:https://www.cnblogs.com/deadwo ...

最新文章

  1. 别学前端了!前端程序员:凭啥??网友:来钱太快你会飘!
  2. oracle 如何获取表的主键列名,如何获取表的所有列名
  3. 在虚拟机中温习DOS
  4. 电大计算机组成原理ppt,四川电大计算机组成原理(0023)第二次形考作业(课程号:5110023).docx...
  5. Quartus 中快速分配器件管脚
  6. PAT A1057 分块思想
  7. Redis 常见的性能问题和解决方法
  8. 查看和修改MySQL数据库表存储引擎
  9. Java 设计模式 之 适配器模式(Adapter)
  10. fastDFS文件系统安装
  11. 网站优化快速排名软件大全
  12. FusionChartsFree及其教程
  13. 图灵大会 | 新观点:AI盛世,其实我们离得还很远
  14. Thumbnails压缩图片
  15. 如何解决“应用程序无法启动,因为应用程序的并行配置不正确“问题
  16. Redis入门——3.Redis key的设计技巧
  17. 深圳计算机发展好的地方,深圳和广州的哪个发达数据比较广州的繁荣还是深圳的繁荣?...
  18. 分享一款在线视频播放器:h-player
  19. 港版plus 6 sim卡显示无服务器,苹果6 plus显示无服务怎么办
  20. 2019年7月训练记录(更新ing)

热门文章

  1. 可爱的python_可爱的Python_课后习题_CDay0 时刻准备着!发布
  2. 实时流协议---RTSP【详解】
  3. java poi 设置行高
  4. 【ANSI转UTF-8】用iconv命令解决Mac/Linux下编码问题
  5. 中国电子书市场谁将成犀利哥?
  6. 聊聊一道简单的javascript面试题
  7. Vivado18.3-Vivado Simulator仿真 学习笔记
  8. nuke py 笔记
  9. Fall2018 学期规划(09/16修订)
  10. 推荐两部昨天刚看完的韩剧