python解析XML文件

python解析XML文件,第1张

概述对于xml的解析,与json原理是相同的。都是摆脱了只是纯文件解析成str的麻烦。无论是json解析还是xml解析,对于python来说都获取了对象,可以拿来直接用。具体方法,看数据文件的格式。但无疑,json更好用,可以直接对应上python的列表或者字典。而xml,需要一些对象、属性处理。至于xml相对JSON
对于xml的解析,与Json原理是相同的。都是摆脱了只是纯文件解析成str的麻烦。无论是Json解析还是xml解析,对于python来说都获取了对象,可以拿来直接用。具体方法,
看数据文件的格式。但无疑,Json更好用,可以直接对应上python的列表或者字典。而xml,需要一些对象、属性处理。至于xml相对JsON的好处,似乎没有什么优势,只因为XML比JsON
产生的时间早,那么在这个比较长的时间里面,形成了一种习惯用法。在表述数据方面因为有<>等的帮助,可能会更清晰一些。但也是仁者见仁罢了。
利用python解析XML的模块,需要遍历根(root)节点及子节点。而节点的属性有4个:tag、attrib、text、tail,在python中用for循环遍历即可。
本文主要用xml.etree.ElementTree模块,最清晰明确。python还有其他两个模块:SAX (simple API for XML )、DOM(document Object Model)可以解析XML文件。但感觉
用法比较繁复,另做探讨。
先设定一个xml文件(xml_lesson):

 1 <data> 2     <country name="LIEchtenstein"> 3         <rank updated="yes">2</rank> 4         <year updated="no">2011</year>tail-尾部 5         <gdppc>141100</gdppc> 6         <neighbor direction="E" name="Austria" /> 7         <neighbor direction="W" name="Switzerland" /> 8     </country> 9     <country name="Singapore">10         <rank updated="yes">5</rank>11         <year updated="no">2014</year>12         <gdppc>59900</gdppc>13         <neighbor direction="N" name="Malaysia" />14     </country>15     <country name="Panama">16         <rank updated="yes">69</rank>17         <year updated="no">2014</year>18         <gdppc>13600</gdppc>19         <neighbor direction="W" name="Costa Rica" />20         <neighbor direction="E" name="Colombia" />21     </country>22      <country name="Panama">23         <rank updated="yes">69</rank>24         <year updated="yes">2013</year>25         <gdppc>13600</gdppc>26         <neighbor direction="W" name="Costa Rica" />27         <neighbor direction="E" name="Colombia" />28     </country>29      <country name="Panama">30         <rank updated="yes">89</rank>31         <year updated="yes">2013</year>32         <gdppc>13600</gdppc>33         <neighbor direction="W" name="Costa Rica" />34         <neighbor direction="E" name="Colombia" />35     </country>36 </data>
VIEw Code

先了解一下xml的结构,树形结构,root很重要:

1 import xml.etree.ElementTree as ET2 xml_file = r"xml_lesson.xml"3 # xml_file=r"movIEs.xml"4 tree = ET.parse(xml_file)5 root = tree.getroot()6 print("root.tag: ", root.tag)  # >>>root.tag:  data7 print("type: %s root.iter %s text: %s :" % (type(root), root.iter, root.text))
VIEw Code

#>>>

root.tag: data
type: <class 'xml.etree.ElementTree.Element'> root.iter <built-in method iter of xml.etree.ElementTree.Element object at 0x0000025EDA942D10> text:

从输出可以看到,所谓的tag就是尖括号最左边靠近括号的内容。一般情况下root没有attrib,也没有text。在后面的子节点可以看到更多的属性。

# 用for循环遍历各级节点,是要知道xml的结构,然后一层一层进行循环。代码如下:

 1 def loop_root(): 2     for i in root:  # 针对根下面第一层标签数据的遍历(有多少个country) 3         print("-->i.tag: ", i.tag, end=' ')  # >>>i.tag:  country 4         # tag属性是data下面的标签定义,如country 5         print("i.attrib: ", i.attrib)  # >>>i.attrib:  {'name': 'LIEchtenstein'} 6         # attrib属性是标签country的key:value键值对。 7         # print("\n") 8         for j in i:  # 针对country下面数据的遍历。 9             print("\t-->", j.tag, end=' ')10             print(j.attrib, end=' ')11             print(j.text)
VIEw Code

执行loop_root()输出结果如下:

#>>>

  -->i.tag: country i.attrib: {'name': 'LIEchtenstein'}

--> rank {'updated': 'yes'} 2
--> year {'updated': 'yes'} 2010
--> gdppc {} 141100
--> neighbor {'direction': 'E', 'name': 'Austria'} None
--> neighbor {'direction': 'W', 'name': 'Switzerland'} None
-->i.tag: country i.attrib: {'name': 'Singapore'}
--> rank {'updated': 'yes'} 5
--> year {'updated': 'yes'} 2013
--> gdppc {} 59900
--> neighbor {'direction': 'N', 'name': 'Malaysia'} None
-->i.tag: country i.attrib: {'name': 'Panama'}
--> rank {'updated': 'yes'} 69
--> year {'updated': 'yes'} 2013
--> gdppc {} 13600
--> neighbor {'direction': 'W', 'name': 'Costa Rica'} None
--> neighbor {'direction': 'E', 'name': 'Colombia'} None

改进的方法,比如只看其中某几个节点,可以把节点名字当做列表参数。代码如下:

1 # 遍历root下各个子节点,参数为节点列表,也可以只输入1个节点名称2 def traverse_child(*child_node_List):3     for child_node in child_node_List:4         for node in root.iter(child_node):5             print(child_node, ":", node.tag, node.attrib,node.text,node.tail)
VIEw Code
执行如下函数:
traverse_child('year')
traverse_child(*['rank','gdppc','neighbor'])

输出如下:

#>>>

year : year {'updated': 'yes'} 2010

year : year {'updated': 'yes'} 2013 tail-content

year : year {'updated': 'yes'} 2013

rank : rank {'updated': 'yes'} 2

rank : rank {'updated': 'yes'} 5

rank : rank {'updated': 'yes'} 69

gdppc : gdppc {} 141100

gdppc : gdppc {} 59900

gdppc : gdppc {} 13600

neighbor : neighbor {'direction': 'E', 'name': 'Austria'} None

neighbor : neighbor {'direction': 'W', 'name': 'Switzerland'} None

neighbor : neighbor {'direction': 'N', 'name': 'Malaysia'} None

neighbor : neighbor {'direction': 'W', 'name': 'Costa Rica'} None

neighbor : neighbor {'direction': 'E', 'name': 'Colombia'} None

# 修改xml文件,更改某些节点的属性。

1 def modify_xml(child_node):2    import xml.etree.ElementTree as ET3    tree = ET.parse("xml_lesson")4    root = tree.getroot()5    for node in root.iter(child_node):6       new_year = int(node.text) + 17       node.text = str(new_year)8       node.set("updated", "no")9    tree.write("xml_lesson")
VIEw Code

执行modify_xml('year')可以修改year节点属性,然后保存xml文件。

# 删除node,可以设定过滤器,删除满足条件的节点。

1 def del_xml_node(child_node, filter):2    import xml.etree.ElementTree as ET3    tree = ET.parse("xml_lesson")4    root = tree.getroot()5    for country in root.findall('country'):6       rank = int(country.find('rank').text)7       if rank > filter:8          root.remove(country)9    tree.write('output.xml')
VIEw Code
执行del_xml_node('country',50),可以按照条件删除一些节点
##按照xml的相关对象创建新的xml文件,构造xml各级节点(标签tag、属性attrib、文本text、尾部tail)。代码如下

 1 def create_xml(): 2     import xml.etree.ElementTree as ET 3     new_xml = ET.Element("nameList") 4     # name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"}) 5     name = ET.SubElement(new_xml, "")  # 函数至少2个参数。 6     name.tag = '名字' 7     name.attrib = {"注册": "yes"} 8     name.text = '张三' 9     age = ET.SubElement(name, "age", attrib={"checked": "no"})10     age.text = '33'11     sex = ET.SubElement(name, "sex")12     sex.text = '男'13     name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})14     name2.text = '李四'15     age = ET.SubElement(name2, "age")16     age.attrib={"青年":"yes"}17     age.text = '19'18     sex = ET.SubElement(name2, "sex")19     sex.text = '女'20 21     et = ET.ElementTree(new_xml)  # 生成文档对象,将根目录转化为xml树状结构(即ElementTree对象)22     pretty_xml(new_xml, '\t', '\n')  # 执行美化方法23 24     ET.dump(new_xml)  # 打印生成的格式,在终端输出xml树内容。25     et.write("test.xml", enCoding="utf-8", xml_declaration=True)
VIEw Code

构造xml,需要了解xml文件的结构,特别是节点的各个属性。值得说明的是,如果不经过修饰,输出的xml就是一个长条,很难看。可以加入如下函数,对xml的

输出进行缩进美化:

 1 ##下面的函数是一个美化xml格式的,如果没有它,生成的xml文档只有1行,很难看。 2 ##有了这个函数,解决了xml按照节点缩进的问题。 3 def pretty_xml(element, indent, newline, level=0): 4     # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行 5     if element:  # 判断element是否有子元素 6         if (element.text is None) or element.text.isspace():  # 如果element的text没有内容 7             element.text = newline + indent * (level + 1) 8         else: 9             element.text = newline + indent * (level + 1) +                             element.text.strip() + newline + indent * (level + 1)11         # else:  # 此处两行如果把注释去掉,Element的text也会另起一行12         # element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level13     temp = List(element)  # 将element转成List14     for subelement in temp:15         if temp.index(subelement) < (len(temp) - 1):16             # 如果不是List的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致17             subelement.tail = newline + indent * (level + 1)18         else:  # 如果是List的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个19             subelement.tail = newline + indent * level20         pretty_xml(subelement, indent, newline, level=level + 1)  # 对子元素进行递归 *** 作
VIEw Code

调用函数create_xml(),确实可以产生能够按照层级缩进的xml文档。

 
总结

以上是内存溢出为你收集整理的python解析XML文件全部内容,希望文章能够帮你解决python解析XML文件所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1185886.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存