xml是一种标记语言,简单、方便在任何程序中读写数据,使其成为一种广泛使用的数据交换语言。

  一、解析xml:element Tree   

  (一)访问某些URL时,常返回带有xml信息的str,解析成xml后,才可操作使用相关数据。

  (二)对.xml文件进行读写及相关数据操作,需要对xml文件进行解析

   P.S.:解析操作的过程是在内存中完成的,若需要将数据保存,需要写入文件。不同解析方式,有不同的写入方式。

#------------------ 使用元素树方式,解析xml--------------------------------

# 导入XML模块
from xml.etree import ElementTree as ET

#### 1、直接解析str为xml对象,获得根节点 ,相关操作后,存入文件####

#### 1.1 在内存中直接将url返回的str转换成xml对象,返回根节点,相关操作后,打开文件,写入保存
# root = ET.XML(ret_str)     # type(root):<class 'xml.etree.ElementTree.Element'>

#     解析后的内容及相关操作,需要写入文件才能保存
# with open('first_xml.xml','wb') as f:
#     f.write(ET.tostring(root))  #  ET.tostring() 的返回结果是bytes类型


#### 1.2 解析xml文件,获得根节点 ,相关操作后,xml对象直接写入文件####

# # 方式一:先加载文件,再解析文件字符串成xml,并获得根节点
# str_xml = open('first_xml.xml','r').read()
# root = ET.XML(str_xml)
# # 相关操作后,需要将修改写入文件
# tree = ET.ElementTree(root)
# tree.write('first_xml.xml',encoding='utf-8')


# # # 方式二:直接解析文件成xml对象,再获取xml对象的根节点
tree = ET.parse('first_xml.xml')
root = tree.getroot()

# # 相关操作后,需要将修改写入文件
# tree.write('first_xml.xml',encoding='utf-8')
View Code

  二、节点操作

  (一)对于节点node,可使用node.tag、node.attrib、node.text分别获得节点的标签名、属性、文本

  (二)node.set(’key‘,’value‘)增加节点属性key=value,del node.attrib['name'] 删除node节点的'name'属性

  (三)node.getchildren() 取node全部子节点,列表形式;node.iter(’name') 取指定子节点‘name',得到的是一个含有全部’name'子节点的生成器

    取指定子节点,还可以使用:node.findall(’name‘)、node.find(’name'),此时直接取得节点,占内存较大。

  (四)添加子节点,可直接使用:ET.subelement(father,son);也可以son = ET.element() 新建节点son后,father.append(son)。

  (五)删除子节点:直接使用:father.remove(son)

#--------------------------对root进行操作--------------------------------
#-------------------------------------------------------------------------
# # 以根节点为例:
# # --------------------------3.1获取节点标签、属性和文本
# print(root.tag)
# print(root.attrib)  # 无属性时:{}
# print(root.text)

# # ----------------------------------3.2添加、删除属性
# # 添加属性
# root.set('name','lucy')
# root.set('age','6')
# # print(root.attrib)
# # 删除属性
# del root.attrib['age']


# # # -----------------------------3.3查看子节点------------
# # # 3.3.1 获得全部子节点
# # 返回子节点列表,列表每一个元素又都是一个节点
# all_son_of_root = root.getchildren()  # type(all_son_of_root):<class 'list'>
# for eve_son in all_son_of_root:
#     print(eve_son, eve_son.text)
#     for son_of_son in eve_son:
#         print(son_of_son.text)

# # 3.3.2 获取指定的子节点
# #node.iter()获取全部‘list’节点
# for node_of_page in root.iter('list'):
#     #获取‘list’节点中的‘page’节点
#     for node_of_page in node_of_page.iter('page'):
#         # 修改节点文本
#         new_page = int(node_of_page.text) + 1
#         node_of_page.text = str(new_page)
#         print(node_of_page.text)
#
# # 获取指定节点之
# print(type(root.iter('list')))       # 返回全部符合条件的生成器,推荐使用,节省内存
# print(type(root.findall('list')))    # 返回全部符合条件的列表
# print(type(root.find('list')))       # 仅返回符合条件的一个节点



#--------------------------3.4添加、删除节点
# 3.4.1添加节点
# 节点标签名字之间不能有空格,如"yes or no"会出现错误的,“yes_or_no"才是正确的
# 方式一:新建节点,添加至指定父节点
# new_son_of_root = ET.Element('yes_or_no',attrib={'y':'好的','n':'不好吧'})  # 创建新节点,添加标签和属性
# new_son_of_root.text = '添加文本' # 为创建的节点添加文本
# root.append(new_son_of_root)   # 将新节点加入根节点
# 方式二:父节点下直接添加子节点
# ET.SubElement(root,'直接添加儿子')


# 3.4.2删除节点
# # 找到需要删除的节点
# for eve in root.iter('yes_or_no'):
#     # 删除指定节点
#     root.remove(eve)

# #添加孙子节点
# new_node= ET.Element('writer',attrib={'school':'btbu'})
# father_node = root.find('list')      # 查找指定节点
# father_node.append(new_node)
#
View Code

  三、优雅打印:缩进和换行

  使用elemnetTree方式解析xml,简单、高效,但是打印时代码可读性差,没有换行和缩进。

  使用dom方式解析xml,虽然功能少、效率低,但是xml.dom.minidom模块,可以优雅显示代码。

  若提高代码打印时的可读性,可在打印时,进行自定义操作:

  1、将elemnetTree解析、操作后的root

  2、ET.tostring(root)将根节点root转成含xml信息的bytes

  3、minidom.parseString(bytes)将含xml信息的bytes转成dom对象***

  4、***.toprettyxml()将***转成换行、缩进的字符串,但含有多余空行

  5、使用正则表达式去掉多余空行

# #------------------------------------------------优雅打印,增强可读性
# # 根节点——》bytes——》dom——》str
#
# from xml.etree import ElementTree as ET
# from xml.dom import minidom
# import re
# # ---------取得待处理xml的根节点
# # 元素树方式打开文件
# tree = ET.parse('first_xml.xml')
# # 获得根节点
# root = tree.getroot()
#
# #----------将xml对象解析成str
# # 由根节点,得到包含xml全部信息的bytes
# root_bytes = ET.tostring(root,encoding='utf-8')
# # 由bytes,得到dom对象
# reparsed_to_dom = minidom.parseString(root_bytes)
# # 由dom对象,得到包含xml全部信息的str
# pretty_str = reparsed_to_dom.toprettyxml(indent='\t')
#
# #------------使用正则表达式去掉多余空行
# # 使用正则去掉空行
# new_pretty_str = re.sub('\n[\s|]*\n','\n',pretty_str)
#
# # --------------优雅打印
# print(new_pretty_str)
# # print(pretty_str)
View Code

  

  P.S.:

  附件:使用的实例‘first_xml.xml’文件代码

<info name="lucy">
   <intro>Book message</intro>
    <list id="001">
        <head>bookone</head>
        <name>python check</name>
        <number>001</number>
        <page>209</page>
        <writer school="btbu" />
    <writer school="btbu" /></list>
    <list id="002">
        <head>booktwo</head>
        <name>python learn</name>
        <number>002</number>
        <page>309</page>
    </list>
    <test_add_node n="不好吧" y="好的">添加文本</test_add_node>
<直接添加儿子 />
</info>
View Code