[python] python xml ElementTree
python xml ElementTree
xml示例
<?xml version="1.0" encoding="utf-8"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
</data>
XML是中结构化数据形式,在ET中使用ElementTree代表整个XML文档,并视其为一棵树,Element代表这个文档树中的单个节点。
解析xml
从硬盘读取xml
(cElementTree为c版本的,速度快,ElementTree为python版本,速度稍慢,有c版本就用c的)
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
tree = ET.parse(self.tempfilename) #打开xml文档
root = tree.getroot() #拿到根节点
element对象属性
- tag: string对象,表示数据代表的种类。
- attrib: dictionary对象,表示附有的属性。
- text: string对象,表示element的内容。
- tail: string对象,表示element闭合之后的尾迹。
- 若干子元素(child elements)。
节点操作
Element.iter(tag=None): [return list] 遍历 该Element所有后代,指定tag进行遍历寻找。
Element.findall(path):[return list]查找当前元素下tag或path能够匹配的 直系节点。
Element.find(path):[return element]查找当前元素下tag或path能够匹配的 首个直系节点。
Element.text: 获取当前元素的text值。
Element.get(key, default=None):获取元素指定key对应的属性值,如果没有该属性,则返回default值。
>>> for child in root:
... print child.tag, child.attrib
...
country {\'name\': \'Liechtenstein\'}
country {\'name\': \'Singapore\'}
country {\'name\': \'Panama\'}
>>> for neighbor in root.iter(\'neighbor\'):
... print neighbor.attrib
...
{\'name\': \'Austria\', \'direction\': \'E\'}
{\'name\': \'Switzerland\', \'direction\': \'W\'}
{\'name\': \'Malaysia\', \'direction\': \'N\'}
{\'name\': \'Costa Rica\', \'direction\': \'W\'}
{\'name\': \'Colombia\', \'direction\': \'E\'}
本次没有进行写操作,所以没研究,先略过。
xml编码问题
这次被python的编码坑了一次。
在网上发现了这么一段话:
python中dom和ElementTree只支持utf-8文件的解析,所以在解析之前不管用什么方法,最好确保文件是utf-8格式的,话说python的文本操作通常用utf-8都是没什么问题的,其它编码方式多多少少都有些麻烦,所以生成文件的时候尽量少用中文编码!
使用utf-8,如果涉及跨平台的时候不要带BOM,也可以采用GBK(尽量不用),但就是 不能使用utf16
。
然而这次要批量处理的xml居然就是utf-16的,心中一万只羊驼跑过!!!
utf-16编码直接按照上述方法Load进来,会报错:
ParseError: encoding specified in XML declaration is incorrect: line 1, column 30
先将xml解析成utf8格式,然后替代第一行的encoding格式,然后保存一个新文件,提供后续解析。
import codecs
f = codecs.open(file_name, \'rb\',\'utf-16\')
text = f.read().encode(\'utf-8\')
text = text.replace(\'<?xml version="1.0" encoding="utf-16"?>\',\'<?xml version="1.0" encoding="utf-8"?>\')
f.close()
tempfilename = file_name.split(\'.xml\')[0]+\'temp.xml\'
f = open(tempfilename, \'wb\')
f.write(text)
f.close()
无意之间用查了一下文件的编码,发现我要处理的xml编码是用utf-8,但是头文件写的是utf-16,所以我上边就不需要codecs.open,直接用open就好了,再把头replace。
linux vim命令 :set fileencoding
Reference
http://blog.csdn.net/gingerredjade/article/details/21944675
http://www.cnblogs.com/CheeseZH/p/4026686.html
http://www.jb51.net/article/67120.htm
http://blog.csdn.net/whzhcahzxh/article/details/33735293
http://blog.csdn.net/jnbbwyth/article/details/6991425/
http://www.cnblogs.com/findumars/p/3620076.html
http://blog.csdn.net/guang11cheng/article/details/7491715