zoukankan      html  css  js  c++  java
  • Python XML解析

      参考:https://www.runoob.com/python/python-xml.html

      什么是XML

      XML 指可扩展标记语言(eXtensible Markup Language)。 

      XML被设计用来传输和存储数据。

      XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。

      它也是元标记语言,即定义了用于定义其他于特定领域有关的,语义的,结构化的标记语言的句法语言。

      Python对XML的解析

      常见的 XML 编程接口有 DOM 和 SAX,这两种接口处理 XML 文件的方式不同,当然使用场合也不同。

      Python 有三种方法解析 XML,SAX,DOM,以及 ElementTree:

      1,SAX(simple API for XML )

      Python 标准库包含 SAX 解析器,SAX 用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。

      2,DOM(Document Object Model)

      将 XML 数据在内存中解析成一个树,通过对树的操作来操作XML。

      3,ELementTree(元素数)

       ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。

      注:因DOM需要将XML数据映射到内存中的树,一是比较慢,二是比较耗内存,而SAX流式读取XML文件,比较快,占用内存少,但需要用户实现回调函数(handler)。

      本章节使用到的 XML 实例文件 movies.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>
    

      本文介绍SAX和DOM两种方式

      python使用SAX解析xml

      SAX是一种基于实践取得的API

      利用SAX解析文档涉及到两个部分:解析器和事件处理器。

      解析器赋值读取XML文档,并像事件处理器发送事件,如元素开始跟元素结束事件。

      而事件处理器则负责对事件作出相应,对传递的XML数据进处理。

      1,对大型文件进行处理

      2,只需要文件的部分内容,或者值需从文件中得到特定的信息。

      3,想建立自己的对象模型时。

      在python中使用sax方式处理xml要先引入xml.sax中的parse函数,还有xml.sax.handler中的ContentHandler类。

      ContentHandler类方法介绍

      characters(content)方法

      调用事件:

      从行开始,遇到标签之前,存在字符,content的值为这些字符串。

      从一个标签,遇到下一个标签之前, 存在字符,content 的值为这些字符串。

      从一个标签,遇到行结束符之前,存在字符,content 的值为这些字符串。

      标签可以是开始标签,也可以是结束标签。  

      startDocument() 方法

      文档启动的时候调用。

      endDocument() 方法

      解析器到达文档结尾时调用。

      startElement(name, attrs)方法

      遇到XML开始标签时调用,name是标签的名字,attrs是标签的属性值字典。

      endElement(name) 方法

      遇到XML结束标签时调用。

      注意:一般使用startElement(name, attrs),characters(content),endElement(name) 这3个方法

      startDoeument() 和endDocument()方法使用较少

      make_parser方法

      以下方法创建一个新的解析器对象并返回

    xml.sax.make_parser( [parser_list] )
    

      参数说明:

    parser_list - 可选参数,解析器列表
    

      parse方法

      以下方法创建一个 SAX 解析器并解析xml文档:

    xml.sax.parse( xmlfile, contenthandler[, errorhandler])
    

      参数说明

    xmlfile - xml文件名
    contenthandler - 必须是一个ContentHandler的对象
    errorhandler - 如果指定该参数,errorhandler必须是一个SAX ErrorHandler对象
    

      parseString方法

       parseString方法创建一个XML解析器并解析xml字符串:

    xml.sax.parseString(xmlstring, contenthandler[, errorhandler])
    

      参数说明

    xmlstring - xml字符串
    contenthandler - 必须是一个ContentHandler的对象
    errorhandler - 如果指定该参数,errorhandler必须是一个SAX ErrorHandler对象
    

      下面举例说明

      创建一个ContentHandler类并使用该类处理XML文本

      以下代码只在类里面使用一个print打印

    # 只演示执行过程不实际处理数据start
    # 导入模块
    import xml.sax
    # 创建一个Handler类继承xml.sax.ContentHandler类
    class Handler(xml.sax.ContentHandler):
    
        def startDocument(self):
            print('startDocument...')
    
        def startElement(self,name,attr):
            print('startElement...')
    
        def characters(self,text):
            print('characters...')              
    
        def endElement(self,name):
            print('endElement...')
    
        def endDocument(self):
            print('endDocument...')
    
    H = Handler()
    test_xml = '<a href="/">python</a>'
    xml_str = xml.sax.parseString(test_xml,H)
    # 输出如下
    # startDocument...
    # startElement...
    # characters...
    # endElement...
    # endDocument...
    # 只演示执行过程不实际处理数据end
    

      从输出可以明显看出执行的顺序为

    # startDocument
    # startElement
    # characters
    # endElement
    # endDocument
    

      以下代码演示各个方法参数对应的内容

    # 演示参数start
    # 导入模块
    import xml.sax
    # 创建一个Handler类继承xml.sax.ContentHandler类
    class Handler(xml.sax.ContentHandler):
    
        def startElement(self,name,attr):
            print('startElement...')
            print('标签名字为 %s' %(name))
            print('标签属性字典%s' %(attr.items()))
    
        def characters(self,text):
            print('characters...')        
            print('标签内部内容为%s' %(text))      
    
        def endElement(self,name):
            print('endElement...')
            print('标签名字为 %s' %(name))
    
    H = Handler()
    test_xml = '<a href="/">python</a>'
    xml_str = xml.sax.parseString(test_xml,H)
    # 输出如下
    # startElement...
    # 标签名字为 a
    # 标签属性字典[('href', '/')]
    # characters...
    # 标签内部内容为python
    # endElement...
    # 标签名字为 a
    # 演示参数end
    

      解析

    本次分析的XML为 '<a href="/">python</a>'
    标签名字为a 标签的写法为<str></str>名字即str
    标签是属性为标签内定义的属性(可为空)即不定义属性,本次定了为href="/" attr为标签是属性字典,使用items即可显示内容
    标签的内容及<a></a>之间的文本 本次为'python'
    

      本次打开的是字符串,如果需要解析xml文档则把xml文档内容保存成文档然后使用以下方法调用

    xml.sax.parse('test.xml',H)
    

      Python解析实例

      为了便于分析,本次把示例只保留一部电影

      movies.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>
    </collection>
    

      解析代码如下

      use_sax_xml.py

    # 使用sax解析movies start
    import xml.sax
    class MoviesHandler(xml.sax.ContentHandler):
        def __init__(self):
            self.currentdata = ''
            self.type = ''
            self.format = ''
            self.year = ''
            self.rating = ''
            self.stars = ''
            self.description = ''
     
        def startElement(self,name,attr):
            self.currentdata = name
            if self.currentdata == 'movie':
                print('***movies***')
                title = attr['title']
                print('Tiele:%s' %(title))
    
        def characters(self,text):
            if self.currentdata == "type":
                self.type = text
            elif self.currentdata == "format":
                self.format = text
            elif self.currentdata == "year":
                self.year = text
            elif self.currentdata == "rating":
                self.rating = text
            elif self.currentdata == "stars":
                self.stars = text
            elif self.currentdata == "description":
                self.description = text
        
        def endElement(self,name):
            if self.currentdata == "type":
                print("Type:", self.type)
            elif self.currentdata == "format":
                print("Format:", self.format)
            elif self.currentdata == "year":
                print("Year:", self.year)
            elif self.currentdata == "rating":
                print("Rating:", self.rating)
            elif self.currentdata == "stars":
                print("Stars:", self.stars)
            elif self.currentdata == "description":
                print("Description:", self.description)
            self.currentdata = ""
    
    H = MoviesHandler()
    
    xml.sax.parse('movies.xml',H)
    
        
    # 使用sax解析movies end
    

      运行输出如下

    ***movies***
    Tiele:Enemy Behind
    Type: War, Thriller
    Format: DVD
    Year: 2003
    Rating: PG
    Stars: 10
    Description: Talk about a US-Japan war
    

      使用调试模式查看执行过程

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

       省略几步 依次处理了以下标签

    <format>DVD</format>
    <year>2003</year>
    <rating>PG</rating>
    <stars>10</stars>
    <description>Talk about a US-Japan war</description>
    

      处理完以上标签输出如下

     

     

     

     

     

     

     

     

       由此可以知道使用SAX执行是逐条语句执行,不需要一次性读取文件至内存

      优点是节约内存,缺点是需要执行写方法,效率低。

      使用xml.dom解析xml

      文件对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口。

      一个 DOM 的解析器在解析一个 XML 文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后你可以利用DOM 提供的不同的函数来读取或修改文档的内容和结构,也可以把修改过的内容写入xml文件。

      python中用xml.dom.minidom来解析xml文件,示例如下:

      使用DOM解析是一次性读取整个文档在内存中生成一个树结构,相比SAX使用更加简单,缺点是占用内存,但是目前服务器内存相对较大,从程序员节约写代码时间来看,可以优先选用DOM。

      DOM解析方法参考:https://www.cnblogs.com/minseo/p/15187837.html

      代码如下

    # 使用dom解析movies start
    # 导入模块
    import xml.dom.minidom
    # 打开xml文档
    dom = xml.dom.minidom.parse('movies.xml')
    # dom.documentElement的到元素对象
    movies = dom.documentElement.getElementsByTagName('movie')
    # getElementsByTagName('movie')从元素对象总查找标签名为movie的对象
    # 得到的对象会组成一个对象列表,本次的对象只有一个
    for movie in movies:
        print("*****Movie*****")
        # 如果对象有属性值title即电影名则打印
        if movie.hasAttribute("title"):
            print("Title: %s" % movie.getAttribute("title"))
        
        # 在从得到的对象中间在搜索对应的标签名对象,本次找的的对象也是一个
        # 使用[0]下标取得取得
        # 使用firstChild.data获取对象的值打印
        type = movie.getElementsByTagName('type')[0]
        print("Type: %s" % type.firstChild.data)
        format = movie.getElementsByTagName('format')[0]
        print("Format: %s" % format.firstChild.data)
        rating = movie.getElementsByTagName('rating')[0]
        print("Rating: %s" % rating.firstChild.data)
        description = movie.getElementsByTagName('description')[0]
        print("Description: %s" % description.firstChild.data)
    # 使用dom解析movies end
    

      输出结果和使用SAX输出是一样的,只不过使用DOM方法代码更加简洁清晰

  • 相关阅读:
    BZOJ 3132: 上帝造题的七分钟 树状数组+差分
    PAT Advanced 1006 Sign In and Sign Out (25 分)
    PAT Advanced 1011 World Cup Betting (20 分)
    PAT Basic 1032 挖掘机技术哪家强 (20 分)
    PAT Basic 1028 人口普查 (20 分)
    PAT Basic 1004 成绩排名 (20 分)
    大数据数据库HBase(二)——搭建与JavaAPI
    PAT Advanced 1009 Product of Polynomials (25 分)(vector删除元素用的是erase)
    PAT Advanced 1002 A+B for Polynomials (25 分)(隐藏条件,多项式的系数不能为0)
    PAT Basic 1041 考试座位号 (15 分)
  • 原文地址:https://www.cnblogs.com/minseo/p/15193400.html
Copyright © 2011-2022 走看看