• 读取只包含标签的xml


    什么是XML

    XML是可扩展标记语言(Extensible Markup Language)的缩写,其中标记是关键部分。用户可以创建内容,然后使用限定标记标记它,从而使每个单词、短语或块成为可识别、可分类的信息。
    标记语言从早起的私有公司和政府制定形式逐渐演变成标准通用标记语言(Standard Generalized Markup Language,SGML)、超文本标记语言(Hypertext Markup Language,HTML),并且最终演变成XML。XML有以下几个特点:

    • XML的设计宗旨是传输数据,而非显示数据
    • XML的标签没有被预定义,用户需要自行定义标签
    • XML被设计为具有自我描述性
    • XML是W3C的推荐标准

    Python对XML文件的解析


           常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的方式不同,使用场合也不同。DOM是由W3C官方提出的标准,它会把整个XML文件读入内存,并将该文件解析成树,我们可以通过访问树的节点的方式访问XML中的标签,但是这种方法占用内存大,解析慢,如果读入文件过大,尽量避免使用这种方法。SAX是事件驱动的,通过在解析XML的过程中触发一个个的事件并调用用户自定义的回调函数来处理XML文件,速度比较快,占用内存少,但是需要用户实现回调函数,因此Python标准库的官方文档中这样介绍SAX:SAX每次只允许你查看文档的一小部分,你无法通过当前获取的元素访问其他元素。Python中提供了很多包支持XML文件的解析,如xml.dom,xml.sax,xml.dom.minidom和xml.etree.ElementTree等,本文重点介绍xml.dom.minidom。

    xml.dom.minidom包

          xml.dom.minidom是DOM API的极简化实现,比完整版的DOM要简单的多,而且这个包也小得多,下面以movie.xml文件为例进行操作。

    <collection shelf="New Arrivals">
    <movie title="Enemy Behind">
       <type>War, Thriller</type>
       <format>DVD</format>
       <year>2003</year>
       <rating>PG</rating>
       <stars>10</stars>
       <description>Talk about a US-Japan war</description>
    </movie>
    <movie title="Transformers">
       <type>Anime, Science Fiction</type>
       <format>DVD</format>
       <year>1989</year>
       <rating>R</rating>
       <stars>8</stars>
       <description>A schientific fiction</description>
    </movie>
       <movie title="Trigun">
       <type>Anime, Action</type>
       <format>DVD</format>
       <episodes>4</episodes>
       <rating>PG</rating>
       <stars>10</stars>
       <description>Vash the Stampede!</description>
    </movie>
    <movie title="Ishtar">
       <type>Comedy</type>
       <format>VHS</format>
       <rating>PG</rating>
       <stars>2</stars>
       <description>Viewable boredom</description>
    </movie>
    </collection>

    然后我们调用xml.dom.minidom.parse方法读入xml文件并解析成DOM树

    from xml.dom.minidom import parse
    import xml.dom.minidom
    
    # 使用minidom解析器打开 XML 文档
    DOMTree = xml.dom.minidom.parse("F:/project/Breast/codes/AllXML/aa.xml")
    collection = DOMTree.documentElement
    if collection.hasAttribute("shelf"):
        print("Root element : %s" % collection.getAttribute("shelf"))
    
    # 在集合中获取所有电影
    movies = collection.getElementsByTagName("movie")
    
    # 打印每部电影的详细信息
    for movie in movies:
        print("*****Movie*****")
        if movie.hasAttribute("title"):
            print("Title: %s" % movie.getAttribute("title"))
    
        type = movie.getElementsByTagName('type')[0]
        print("Type: %s" % type.childNodes[0].data)
        format = movie.getElementsByTagName('format')[0]
        print("Format: %s" % format.childNodes[0].data)
        rating = movie.getElementsByTagName('rating')[0]
        print("Rating: %s" % rating.childNodes[0].data)
        description = movie.getElementsByTagName('description')[0]
        print("Description: %s" % description.childNodes[0].data)

    以上程序执行结果如下:

    Root element : New Arrivals
    *****Movie*****
    Title: Enemy Behind
    Type: War, Thriller
    Format: DVD
    Rating: PG
    Description: Talk about a US-Japan war
    *****Movie*****
    Title: Transformers
    Type: Anime, Science Fiction
    Format: DVD
    Rating: R
    Description: A schientific fiction
    *****Movie*****
    Title: Trigun
    Type: Anime, Action
    Format: DVD
    Rating: PG
    Description: Vash the Stampede!
    *****Movie*****
    Title: Ishtar
    Type: Comedy
    Format: VHS
    Rating: PG
    Description: Viewable boredom

    实战—批量修改XML文件


    最近在用caffe-ssd训练比赛的数据集,但是官方给的数据集用来标记的XML文件并不是标准格式,一些标签的命名不对,导致无法正确生成lmdb文件,因此需要修改这些标签,下面用Python实现了一个批量修改XML文件的脚本。

    # -*- coding:utf-8 -*-
    
    import os
    
    import xml.dom.minidom
    
    xml_file_path = "/home/lyz/data/VOCdevkit/MyDataSet/Annotations/"
    lst_label = ["height", "width", "depth"]
    lst_dir = os.listdir(xml_file_path)
    
    
    for file_name in lst_dir:
        file_path = xml_file_path + file_name
        tree = xml.dom.minidom.parse(file_path)
        root = tree.documentElement        #获取根结点
        size_node = root.getElementsByTagName("size")[0]
        for size_label in lst_label:    #替换size标签下的子节点
            child_tag = "img_" + size_label
            child_node = size_node.getElementsByTagName(child_tag)[0]
            new_node = tree.createElement(size_label)
            text = tree.createTextNode(child_node.firstChild.data)
            new_node.appendChild(text)
            size_node.replaceChild(new_node, child_node)
    
        #替换object下的boundingbox节点
        lst_obj = root.getElementsByTagName("object")
        data = {}
        for obj_node in lst_obj:
            box_node = obj_node.getElementsByTagName("bounding_box")[0]
            new_box_node = tree.createElement("bndbox")
            for child_node in box_node.childNodes:
                tmp_node = child_node.cloneNode("deep")
                new_box_node.appendChild(tmp_node)
            x_node = new_box_node.getElementsByTagName("x_left_top")[0]
            xmin = x_node.firstChild.data
            data["xmin"] = (xmin, x_node)
            y_node = new_box_node.getElementsByTagName("y_left_top")[0]
            ymin = y_node.firstChild.data
            data["ymin"] = (ymin, y_node)
            w_node = new_box_node.getElementsByTagName("width")[0]
            xmax = str(int(xmin) + int(w_node.firstChild.data))
            data["xmax"] = (xmax, w_node)
            h_node = new_box_node.getElementsByTagName("height")[0]
            ymax = str(int(ymin) + int(h_node.firstChild.data))
            data["ymax"] = (ymax, h_node)
    
    
            for k, v in data.items():
                new_node = tree.createElement(k)
                text = tree.createTextNode(v[0])
                new_node.appendChild(text)
                new_box_node.replaceChild(new_node, v[1])
            obj_node.replaceChild(new_box_node, box_node)
    
        with open(file_path, 'w') as f:
            tree.writexml(f, indent="
    ", addindent="	", encoding='utf-8')
    
        #去掉XML文件头(一些情况下文件头的存在可能导致错误)
        lines = []
        with open(file_path, 'rb') as f:
            lines = f.readlines()[1:]
        with open(file_path, 'wb') as f:
            f.writelines(lines)
    
    print("-----------------done--------------------")

    关于writexml方法:indent参数表示在当前节点之前插入的字符,addindent表示在该结点的子节点前插入的字符

  • 相关阅读:
    【html】页面制作规范文档
    【jquery】blockUI 弹出层
    前端攻城师所要掌握的知识和技能
    【html】edm 邮件制作指南
    【css】教你如何写出高效整洁的 css 代码——css优化
    前端开发神器notepad++以及zen coding神级插件
    百度统计流量研究院——了解互联网行业基本数据分布和趋势
    【css】我的 css 框架——base.css
    通过扩展方法 链式方法 为MVC 3 视图添加验证
    使用正则表达式抓取博客园列表数据
  • 原文地址:https://www.cnblogs.com/ziytong/p/11106381.html
Copyright © 2020-2023  润新知