您的位置:首页 > 编程语言 > Python开发

python之xml文件处理的例子-问题描述及解决方法

2016-02-14 11:11 896 查看
待解决问题描述:

多个XML文件,具有相同的格式,如下:

<?xml version="1.0" encoding="UTF-8"?>
<test  name="F000 ">
…
</test>
<test  name="F001 ">
…
</test>
<test  name="F002 ">
…
</test>
…
不同xml文件中的<test>标签个数不同。有的50个,有的80个。

代码目标:

提取test 标签的 name 属性值,将这些值保存到excel文件中,并为每个值加上日期。生成表格如下:

F000

1月6日

F001

1月6日

F002

1月6日



1月6日

说明:每个xml文件会生成一个如上的表格。将所有这些表格保存到同一个excel文件中。

解决步骤:

1. 解析xml

方法一:使用python API SAX .

http://www.runoob.com/python/python-xml.html

方法二:使用xml.dom

Dom 方法将xml文件一次性读取,保存在一个树形结构中,读取文档内容很方便。

2. csv module写excel文件

很多码友分享可以用csv模块处理,将提取的文件写入csv文件,excel会将csv格式转换成表格。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
testname = [‘F000’,’F001’,’F002’]
import csv
#write to file
with open('report.csv', 'w') as csvfile:
spamwriter = csv.writer(csvfile,dialect='excel')
for item in testname:
spamwriter.writerow(item)
csvfile.close()


list 变量testname 保存目标字符串,将其存入到python 的list中。

然后import csv模块写入文件report.csv。

遇到的问题一:中文编码

参考的文章:

/article/10700096.html

http://www.crifan.com/summary_python_2_x_common_string_encode_decode_error_reason_and_solution/

当目标字符串中含有中文时,xml模块读入此字符串后,存为unicode。

用下面方法打印看看:

print isinstance(testname[1], unicode)


打印为True。

尽管在python文件的开头声明了编码方式:# -*- coding: UTF-8 -*- , 中文字符串依然以unicode编码保存。

有意思的是,testname变量是一个list, 它里面的元素被存为unicode, 但如果查看testname 这个list的编码方式,发现打印为False, 即它不是用unicode编码。

查阅python的帮助文档,摘下描述:

The
csv module doesn’tdirectly support reading and writing Unicode, but it is 8-bit-clean save forsome problems with ASCII NUL characters. So you can write functions or classesthat handle the encoding and decoding for you as
long as you avoid encodingslike UTF-16 that use NULs. UTF-8 is recommended.

说明csv module 不直接处理unicode格式。

这就是为什么调用spamwriter.writerow(item) 方法时报错UnicodeEncodeError的原因。

UnicodeEncodeError: 'ascii' codec can't encode characters in position 5-8: ordinal not in range(128)


使用str 的encode方法将unicode转换为UTF-8后运行成功。

spamwriter.writerow(item .encode('UTF-8'))


成功生成report.csv文件后,用MS office打开,新问题出现——中文乱码。

暂时没找到办法用代码解决,找到一条百度经验,试验有效:

http://jingyan.baidu.com/article/3c48dd3464b46ce10be3581f.html

遗留的问题:notepad中可以正常显示日期:2016/1/30

但如百度经验中操作后,用excel打开却显示: ######## 。在此单元格上双击则正常显示出日期。再换个单元格双击,整个列的日期都正常显示出来。奇怪~~

遇到的问题二:生成的excel文件中多一行空白。

参考的文章:

/article/9641683.html

我用的版本是python27, 写成如下就没有问题了。用‘wb’方式打开csv 文件。

with open('report.csv', 'wb') as csvfile:


补充,由于是需要对多个xml文件处理,希望把不同文件中提取出的目标字符串保存到同一个文件中,因使用增量方式写文件,将'wb'改为'ab'

with open('report.csv', 'ab') as csvfile:


3. 用xlrd等excel处理工具。待学习。。。

4. 遍历文件 http://www.jb51.net/article/54640.htm
遇到问题三:对路径的处理。

由于路径中存在’\’, 直接把一个路径赋值给一个变量的时候,需要转义,即为c:\\mypath。要处理该路径下某个文件时,又需要使用其原始的,非转义的路径,即c:\mypath。 处理不当导致错误:

IOError: [Errno 2] No such file or directory: 'D:\\Python27\\works\\RFlogxml\\xmlst.xml'


os.path.join 处理路径,参考下面的文章:

/article/2513234.html

例如:在C:\TDDOWNLOAD目录下有a.txt、b.txt两个文件,另有\sub1子文件夹,C:\TDDOWNLOAD\sub1下又有c.txt、d.txt两个文件。

1. os.walk
os.walk()返回一个三元素的tuple:当前路径、子文件夹名称、文件列表。
>>> import os
>>> def fun( path ):
... for root, dirs, files in os.walk( path ):
... for fn in files:
... print root, fn
...
>>> fun( r'C:\TDDOWNLOAD' )
C:\TDDOWNLOAD a.txt
C:\TDDOWNLOAD b.txt
C:\TDDOWNLOAD\sub1 c.txt
C:\TDDOWNLOAD\sub1 d.txt
>>>

2. glob.glob
glob.glob()只接受一个参数,这个参数既代有路径,又代有匹配模式,返回值为一个列表。注意,glob.glob()无法直接穿透子文件夹,需要自己处理:
>>> def fun( path ):
... for fn in glob.glob( path + os.sep + '*' ): # '*'代表匹配所有文件
... if os.path.isdir( fn ): # 如果结果为文件夹
... fun( fn ) # 递归
... else:
... print fn
...
>>> fun( r'C:\TDDOWNLOAD' )
C:\TDDOWNLOAD\a.txt
C:\TDDOWNLOAD\b.txt
C:\TDDOWNLOAD\sub1\c.txt
C:\TDDOWNLOAD\sub1\d.txt
>>>

'*'为匹配模式,代表匹配所有文件,只有这样才能将子文件夹查出来,以便递归深入,探查下一层的文件。


参考如下文章的处理方式:

/article/2513234.html

**folderTravel.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import xmlparserDOM  as parser
import re
#/article/2513234.html

rootdir = os.getcwd()
print('rootdir = ' + rootdir)

for (dirpath, dirnames, filenames) in os.walk(rootdir):
#print('dirpath = ' + dirpath)
for dirname in dirnames:
print('dirname = ' + dirname)
for filename in filenames:
if re.search('.xml', filename):
#print(os.path.join(dirpath, filename))
#xml files and py files are in the same directory
parser.func(filename)


os.getcwd 获取当前文件所在路径,避免指定路径字符串。

用os.walk遍历当前文件夹,获取xml文件名。

因为得到的结果中会列出所有文件包括python脚本文件及xml名件,需要过滤掉py文件,因引入remodule匹配(.xml)文件。

parser.func 为步骤1,2中的处理过程。意思是找到一个xml文件,就按照步骤1,2处理一遍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: