• python常用内置模块之xml模块


    一.简介

    xml是实现不同语言或程序之间进行数据交换的协议,可扩展标记语言,标准通用标记语言的子集。是一种用于标记电子文件使其具有结构性的标记语言。xml格式如下,是通过<>节点来区别数据结构的。

    xml(可扩展标记语言),它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。从结构上,很像HTML超文本标记语言。但他们被设计的目的是不同的,html被设计用来显示

    数据,其焦点是数据的外观。xml被设计用来传输和存储数据,其焦点是数据的内容。

    二.XML文件处理

    ElementTree是python的XML处理模块,它提供了一个轻量级的对象模型。在使用ElementTree模块时,需要import  xml.etree.ElementTree 的操作。ElementTree表示整个XML节点树,而Element表示节点树中

    的一个单独的节点。

    创建XML文件

    ElementTree(tag)        其中tag表示根节点,初始化一个ElementTree(节点树)对象

    Element (tag, attrib={}, **extra)  函数用来构造XML的一个根节点,其中tag表示根节点的名称 ; attrib是一个可选项,表示节点的属性。

    SubElement(parent, tag, attrib={}, **extra)用来构造一个已经存在的节点的子节点

    Element.text和SubElement.text    表示element(节点)对象的额外的内容属性,

    Element.tag和Element.attrib         分别表示element对象的标签和属性。

    ElementTree.write(file, encoding='us-ascii', xml_declaration=None, default_namespace=None, method='xml')  函数新建一个XML文件,并且将节点数数据写入XML文件中。

    下面以新建一个网站的sitemap.xml文件为例进行代码示例 

    from xml.etree import ElementTree as ET  #加载模块,设置一个别名
    def build_sitemap(): urlset = ET.Element("urlset")   #设置一个根节点,标签为urlset url = ET.SubElement(urlset,"url") #在根节点urlset下建立子节点 loc = ET.SubElement(url,"loc") loc.text = "http://www/baidu.com" #text属性--文本 lastmod = ET.SubElement(url,"lastmod")#在根节点urlset下建立子节点,和loc是同级节点 lastmod.text = "2017-10-10" changefreq = ET.SubElement(url,"changefreq") changefreq.text = "daily" priority = ET.SubElement(url,"priority") priority.text = "1.0" tree = ET.ElementTree(urlset)   #ElementTree(tag)初始化一个ElemntTree对象,tag表示根节点 tree.write("sitemap.xml")      #ET对象方法write(),新建一个XML文件,并且将节点数数据写入XML文件中。 if __name__ == '__main__': build_sitemap()

    生成的xml文件在浏览器打开显示为:

    <urlset>
        <url>
            <loc>http://www/baidu.com</loc>
            <lastmod>2017-10-10</lastmod>
            <changefreq>daily</changefreq>
            <priority>1.0</priority>
        </url>
    </urlset>                

    解析和修改XML文件

    ElementTree.parse(source, parser=None)    将xml文件加载并返回ElementTree对象 ;parser是一个可选的参数,如果为空,则默认使用标准的XMLParser解析器。

    ElementTree.getroot()             得到根节点。返回根节点的element对象。

    Element.remove(tag)             删除root下名称为tag的子节点 以下函数,ElementTree和Element的对象都包含。

    find(match)          得到第一个匹配match的子节点,match可以是一个标签名称或者是路径。返回个element

    findtext(match,default=None)  得到第一个配置的match的element的文本内容

    findall(match)         得到匹配match下的所有的子节点 ;match可以是一个标签或者是路径,它会返回一个list,包含匹配的elements的信息

    iter(tag)            创建一个以当前节点为根节点iterator(可以被for循环)

    set()            设置属性

    del  attrib[‘属性名’]           删除属性,每个属性都是一个键值对

    还是以上面创建的sitemap.xml为例,对其进行一定的修改,代码示例如下:

    from xml.etree import ElementTree as ET
    tree = ET.parse("sitemap.xml")     #将xml文件加载并返回一个ET对象
    url = tree.find("url")          #返回第一个匹配的子节点
    for rank in tree.iter('loc'):      #创建一个以当前节点为根节点的iterator迭代器
        rank.text = "http://www.adminba.com"
    tree.write("sitemap.xml")        #将节点数数据写入XML文件中。

    将url修改为http://www.adminba.com了

    <urlset>
        <url>
            <loc>http://www.adminba.com</loc>
            <lastmod>2017-10-10</lastmod>
            <changefreq>daily</changefreq>
            <priority>1.0</priority>
        </url>
    </urlset>                

     ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    下面进行更深入的学习:(长段警告!!)

    XML文件示例:

    <?xml version="1.0"?> #声明是xml文件,版本号1.0  缩进代表了层级关系
    <data>            # data 是根节点 <>开头<>结尾就表示为一个节点
        <country name="Liechtenstein">    # country节点,name是节点的属性,属性可以有多个,属性值必须用引号 ; 属性是键值对!
            <rank updated="yes">2</rank>  # rank节点,updated是节点的属性,2 是文本内容
            <year>2023</year>
            <gdppc>141100</gdppc>
            <neighbor direction="E" name="Austria" />
            <neighbor direction="W" name="Switzerland" />
        </country>
        <country name="Panama">
            <rank updated="yes">69</rank>
            <year>2026</year>
            <gdppc>13600</gdppc>
            <neighbor direction="W" name="Costa Rica" />
            <neighbor direction="E" name="Colombia" />
        </country>
    </data>    

    可以通过在线工具进行格式化或压缩

    XML文件解析: 1. 字符串解析  2.解析文件  ----共同点,都要拿到根节点root

    a.解析字符串方式
    # 加载模块,设置一个别名
    from xml.etree import ElementTree as ET
     
    # 打开文件,读取XML内容,print(str_xml)则获得整个xml文件中的内容,str_xml是个字符串
    str_xml = open('sitemap.xml', 'r').read()
     
     
    # 将字符串解析成xml特殊对象,root代指xml文件的根节点,print(root)将获取根节点的内存地址,print(root.tag)可以获取根节点的名称
    root = ET.XML(str_xml)


    b.解析文件方式
    from xml.etree import ElementTree as ET # 直接解析xml文件 tree = ET.parse("sitemap.xml") # 获取xml文件的根节点 root = tree.getroot()

    XML文件操作:

    1.遍历XML文档中的所有内容

    from xml.etree import ElementTree as ET
    ############ 解析方式一 ############
    # 打开文件,先读取XML内容,在转换成XML对象
    #str_xml = open('sitemap.xml', 'r').read()
    # 将字符串解析成xml特殊对象,root代指xml文件的根节点
    #root = ET.XML(str_xml) 


    #
    ########### 解析方式二 ############ # 直接解析xml文件 tree = ET.parse("xo.xml") # 获取xml文件的根节点 root = tree.getroot() # 顶层标签 print(root.tag) # 遍历XML文档的第二层 for child in root: # 第二层节点的标签名称和标签属性     print(child.tag, child.attrib) # 遍历XML文档的第三层 for i in child: # 第三层节点的标签名称和内容 print(i.tag,i.text) # 输出 country {'name': 'Liechtenstein'} rank 2 year 2023 gdppc 141100 neighbor None neighbor None country {'name': 'Panama'} rank 69 year 2026 gdppc 13600 neighbor None neighbor None

    2.遍历XML中指定的节点

    ...
    解析xml文件,获得根节点
    ...
    root = ET.XML(str_xml)
    或者
    root = tree.getroot()
    
    # 遍历XML中所有的year节点
    for node in root.iter('year'):
        
        print(node.tag, node.text)    # 节点的标签名称和内容
    # 输出
    year 2023
    year 2026

     

    修改节点内容:

    由于修改节点时,都在内存中进行,不会影响原文件中的内容。如果想要保存修改,则会要将内存中的内容写入文件。

    (1)解析字符串方式的修改和保存

    from xml.etree import ElementTree as ET
    # 打开文件,先读取XML内容,返回字符串
    str_xml = open('sitemap.xml', 'r').read()
    # 将字符串解析成xml特殊对象,返回xml文件的根节点
    root = ET.XML(str_xml)

    # 顶层标签,根节点的标签 print(root.tag) # 循环所有的year节点 for node in root.iter('year'): # 将year节点中的内容+1 temp_year = int(node.text) + 1 #节点的text方法获得的是文本字符串,要强制转换类型, node.text = str(temp_year) # 设置当前year节点的属性 node.set('name', 'alex') node.set('age', '18') # 删除属性 del node.attrib['name'] ############ 保存文件 ############ tree = ET.ElementTree(root)                #初始化一个ElementTree(节点树)对象,类的实例化 tree.write("new_sitemap.xml", encoding='utf-8')     #python默认utf-8编码格式,主要是为了解决汉字的乱码问题

    (2)解析文件方式的修改和保存

    from xml.etree import ElementTree as ET
    # 直接解析xml文件
    tree = ET.parse("sitemap.xml")
    # 获取xml文件的根节点,
    root = tree.getroot()
    # 顶层标签
    print(root.tag)
    
    
    # 循环所有的year节点
    for node in root.iter('year'):
        # 将year节点中的内容自增一
        new_year = int(node.text) + 1
        node.text = str(new_year)
      
        # 设置属性
        node.set('name', 'alex')
        node.set('age', '18')
        # 删除属性
        del node.attrib['name']
    
    ############ 保存文件 ############
    tree.write("newnew.xml", encoding='utf-8')    #区别在于,tree已经是ET对象了,拥有write方法 ,不用再实例化了

    删除节点

     (1)以解析字符串方式打开XML文件的删除

    from xml.etree import ElementTree as ET
    ############ 解析字符串方式打开 ############
    # 打开文件,读取XML内容
    str_xml = open('sitemap.xml', 'r').read()
    # 将字符串解析成xml特殊对象,返回xml文件的根节点
    root = ET.XML(str_xml)
    # 顶层标签
    print(root.tag)
    
    
    # 遍历data下的 所有country节点
    for country in root.findall('country'):
        # 获取每一个country节点下rank节点的内容
        rank = int(country.find('rank').text)     #站在country节点,往下找
     
        if rank > 50:
            # 删除指定country节点
            root.remove(country)        #删除是站在顶层标签root节点,往下找然后删除
    
    ############ 保存文件 ############
    tree = ET.ElementTree(root)
    tree.write("newnew.xml", encoding='utf-8')

    (2)以解析文件方式打开的删除

    from xml.etree import ElementTree as ET
    
    # 直接解析xml文件
    tree = ET.parse("sitemap.xml")
    # 获取xml文件的根节点
    root = tree.getroot()
    # 顶层标签
    print(root.tag)
    
    
    # 遍历data下的所有country节点
    for country in root.findall('country'):
        # 获取每一个country节点下rank节点的内容
        rank = int(country.find('rank').text)
     
        if rank > 50:
            # 删除指定country节点
            root.remove(country)
    ############ 保存文件 ############
    tree.write("newnew.xml", encoding='utf-8')      #区别就在最后,tree已经是ET对象了,可以直接write

    创建XML文件

    (1)创建方式一: 先用Element()初始化创建一个个节点,然后进行添加,形成父子关系

    from xml.etree import ElementTree as ET
    
    # 创建根节点
    root = ET.Element("famliy")
    # 创建节点大儿子
    son1 = ET.Element('son', {'name': '儿1'})
    # 创建小儿子
    son2 = ET.Element('son', {"name": '儿2'})
    
    # 在大儿子中创建两个孙子
    grandson1 = ET.Element('grandson', {'name': '儿11'})
    grandson2 = ET.Element('grandson', {'name': '儿12'})
    son1.append(grandson1)
    son1.append(grandson2)
    
    # 把儿子添加到根节点中,形成节点关系
    root.append(son1)
    root.append(son1)
    
    tree = ET.ElementTree(root)    #实例化ET对象,然后写入xml文件
    tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False) 

    (2)创建方式二:利用  父结点 . makeelement("标签":{属性} )  替代 Element() 初始化一个节点

    from xml.etree import ElementTree as ET
    
    # 创建根节点
    root = ET.Element("famliy")
    # 创建大儿子
    # son1 = ET.Element('son', {'name': '儿1'})
    son1 = root.makeelement('son', {'name': '儿1'})    
    # 创建小儿子
    # son2 = ET.Element('son', {"name": '儿2'})
    son2 = root.makeelement('son', {"name": '儿2'})
    
    # 在大儿子中创建两个孙子
    # grandson1 = ET.Element('grandson', {'name': '儿11'})
    grandson1 = son1.makeelement('grandson', {'name': '儿11'})
    # grandson2 = ET.Element('grandson', {'name': '儿12'})
    grandson2 = son1.makeelement('grandson', {'name': '儿12'})
    son1.append(grandson1)
    son1.append(grandson2)
    
    # 把儿子添加到根节点中
    root.append(son1)
    root.append(son1)
    
    tree = ET.ElementTree(root)
    tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)    

    (3)创建方式三:利用SubElement(parent, tag, attrib={}) 用来构造一个已经存在的节点的子节点  ,parent 父节点 tag标签     --------------------------》推荐!!!!,容易记忆!!

    from xml.etree import ElementTree as ET
    
    # 创建根节点
    root = ET.Element("famliy")
    # 创建节点大儿子
    son1 = ET.SubElement(root, "son", attrib={'name': '儿1'})
    # 创建小儿子
    son2 = ET.SubElement(root, "son", attrib={"name": "儿2"})
    
    # 在大儿子中创建一个孙子
    grandson1 = ET.SubElement(son1, "age", attrib={'name': '儿11'})
    grandson1.text = '孙子'
    
    tree = ET.ElementTree(root)  #生成文档对象
    tree.write("test.xml", encoding="utf-8", xml_declaration=True, short_empty_elements=False)

    以上创建方式的XML默认无缩进

    例如方法三生成的xml文件为

    <?xml version='1.0' encoding='utf-8'?>
    <famliy><son name="儿1"><age name="儿11">孙子</age></son><son name="儿2"></son></famliy>

    如果要设置缩进的话,需要修改保存方式:--------------------------》这便是BeautifulSoup存在的意义!!!

    from xml.etree import ElementTree as ET
    from xml.dom import minidom        #minidom模块,进行DOM写入和DOM解析 


    def
    prettify(elem):               """将节点转换成字符串,并添加缩进。        >BeautifulSoup模块!! """ rough_string = ET.tostring(elem, 'utf-8') reparsed = minidom.parseString(rough_string) return reparsed.toprettyxml(indent=" ") # 创建根节点 root = ET.Element("famliy") # 创建大儿子 # son1 = ET.Element('son', {'name': '儿1'}) son1 = root.makeelement('son', {'name': '儿1'}) # 创建小儿子 # son2 = ET.Element('son', {"name": '儿2'}) son2 = root.makeelement('son', {"name": '儿2'}) # 在大儿子中创建两个孙子 # grandson1 = ET.Element('grandson', {'name': '儿11'}) grandson1 = son1.makeelement('grandson', {'name': '儿11'}) # grandson2 = ET.Element('grandson', {'name': '儿12'}) grandson2 = son1.makeelement('grandson', {'name': '儿12'}) son1.append(grandson1) son1.append(grandson2) # 把儿子添加到根节点中 root.append(son1) root.append(son1)
    raw_str
    = prettify(root)      

    f
    = open("xxxoo.xml",'w',encoding='utf-8') f.write(raw_str) f.close()

    python中文文档 https://docs.python.org/zh-cn/3/library/xml.html

    参考自 https://www.cnblogs.com/ginvip/p/6891534.html 

         https://www.cnblogs.com/wang-yc/p/5623393.html

     
  • 相关阅读:
    UVALive
    UVALive
    UVA
    UVALive
    BZOJ3597 SCOI2014方伯伯运椰子(分数规划+spfa)
    BZOJ3456 城市规划(多项式求逆)
    BZOJ4182 Shopping(点分治+树形dp)
    BZOJ4383 Pustynia(线段树+拓扑排序)
    BZOJ4445 SCOI2015小凸想跑步(半平面交)
    BZOJ5311 贞鱼(动态规划+wqs二分+决策单调性)
  • 原文地址:https://www.cnblogs.com/hemengjita/p/12349588.html
Copyright © 2020-2023  润新知