zoukankan      html  css  js  c++  java
  • 【Python】 xml解析与生成 xml

    xml

      *之前用的时候也没想到。。其实用BeautifulSoup就可以解析xml啊。。因为html只是xml的一种实现方式吧。但是很蛋疼的一点就是,bs不提供获取对象的方法,其find大多获取的都是字符串,这就导致不得不一遍遍地连续通过bs总对象来定位元素再输出这样子。挺麻烦的。

      xml是一种常用的网络通讯格式,也是一种文件的格式。xml包里有多种不同的可用于解析&生成文件的模块,比如:

        xml.dom.minidom

        xml.etree.ElementTree

        xml.aix等等。这三者比较起来,minidom最贴近底层代码,但是写起来也最烦。本文主要通过ElementTree来解析&生成。尽管ElementTree也有很多不合理的地方,但是可以通过修改源码,重载源码的部分方法来解决。

      ■  ElementTree基本用法

    from xml.etree import ElementTree
    
    doc = ElementTree.parse("文件路径"or"文件对象"[,parser=...])
    '''
    虽然也可用ElementTree直接来生成文件对象,但是用parse来生成的话可以指定parser。这个parser后面会讲到有什么作用
    '''

      所得到的doc对象就是文件的根节点对象。所谓根节点,就是整个文件第一对有效的标签所指代的节点。

      ●  对于每个节点,都有:

        .text  代表该节点的文本内容(和bs一样,那些有子孙元素但是本身没有内容的节点的这个属性是空串,需要注意)

        .attrib  代表该节点的属性(字典形式)

        .tag  代表该节点的tag名

      ●  而对于包括根节点在内的所有节点都有以下节点可调用的方法:

        .find("tag名")  找出其子节点中第一个指定tag名的节点

        .findall("tag名")  找出所有子节点which是指定的tag名,返回一个列表

        .findtext("tag名")  找出相应子节点的文本内容,相当于上面的find找到对象之后再访问其.text属性

        //以上三个方法都是只检索子节点,不检索孙节点以及更加后辈的节点

        .getiterator([tag])  从当前节点开始,生成一个迭代器,里面是遍历了包括当前节点在内的所有后辈节点。tag参数相当于一个filter,指定tag的话迭代器只返回tag名和给出值一致的节点。

        *以上的那些find啥啥的方法,里面的tag名其实是有语法的。单纯的"tag"就只检索当前节点的子节点中名为tag的节点。如果是'.//tag'的话就是搜索所有后辈节点中的tag节点了。更多具体的语法可以参见python参考手册,就不多说了

      ●  另外,ElementTree也在节点对象中实现了几个magic method,所以节点(这次不包括根节点了)也有了如下借口:

        elem[n]  节点elem的第n个子节点(不是n+1个!

        del elem[n]  删除elem的第n个子节点

        len(elem)  子节点的个数

        elem[n] = newElement  将某个子节点替换成另外一个element

       ●  对于非根节点,还有以下的一些方法:

        clear()  清空所有后辈节点

        append(Element)  加入一个新子节点

        get(key)  获取某个属性的值

        insert(index,Element)  将子节点插入某个特定的位置

        remove(Element)  从该节点中移除一个子节点

        set(key,value)  设置某个节点的属性值

      ●  关于Element的构造方法

        上面很多方法都用element作为参数,那么element是怎么来的,就要用到Element构造方法了。

        ElementTree.Element(tag[,attrib])  构造一个Element,但是没有文本内容

        ElementTree.XML("xmlcode")  将一段xml代码转化为一个Element对象,比较实用

        ElementTree.Comment("text")  生成一段注释的Element对象

       ●  最后,ElementTree还提供了几个类方法

        ElementTree.dump(Element)  把相关element的内容打印出来,主要用于调试。因为element对象普遍没有实现__repr__方法

        ElementTree.iselement(element)  判断某个对象是不是有效的element对象

     以上的所有操作都是对存储在内存中的一个XMLTree对象的改动,要想保存成文件,只要根节点调用方法write即可

    doc.write("文件路径"or"w模式文件对象"[,encoding=xxx])

     这里面的encoding参数也有点意思。encoding的默认值是utf-8,当encoding被指定且不是utf-8或者ascii的时候,在新生成的文件头上自动会加一条<?xml version="1.0" encoding="xxx">

      *ElementTree有一个很大的问题,就是在默认情况下,会吃掉所有注释内容。

       这种现象的原因是因为,源码中默认的TreeBuilder(这个类的作用是构建一个对象,这个对象用来存储抽象化后的文件内容。)在建立Tree对象的时候没有写处理注释的方法。

       解决方法是自己写个CommentedTreeBuilder类来重载处理注释:

    class CommentedTreeBuilder(XMLTreeBuilder):
        
        def __init__(self, html=0, target=None):
            XMLTreeBuilder.__init__(self, html, target)
            self._parser.CommentHandler = self.handle_comment    #指定处理comment的方法。
    
        def handle_comment(self, data):
            '''
            默认的处理comment的方法是什么都不做直接pass,而在这个方法里,通过start,data和end三个方法,相当于把注释的内容原封不动地复制到创建的Tree对象里去,使得注释得以保存
            '''
            self._target.start(Comment, {})
            self._target.data(data)
            self._target.end(Comment)

      handle_comment方法接受的参数data是一个ascii字符串或者unicode字符串。当有中文字符时无疑data是unicode。如果在write的时候不指明encoding类型的话可能会出现写入中文字符出错,变成其编码的格式了。解决办法就是在write的时候指出encoding参数如encoding='UTF-8'

  • 相关阅读:
    Java 接口
    Java 数据结构
    Java 包(package)
    一步步学习SPD2010--第四章节--创建和修改网页(9)--附上母版页
    一步步学习SPD2010--第四章节--创建和修改网页(8)--插入Web部件区域
    一步步学习SPD2010--第四章节--创建和修改网页(7)--创建ASP.NET页面
    一步步学习SPD2010--第四章节--创建和修改网页(6)--创建和修改列表表单页面
    一步步学习SPD2010--第四章节--创建和修改网页(5)--创建列表视图页面
    一步步学习SPD2010--第四章节--创建和修改网页(4)--修改列表视图页面
    一步步学习SPD2010--第四章节--创建和修改网页(3)--改变网站的首页
  • 原文地址:https://www.cnblogs.com/franknihao/p/6562349.html
Copyright © 2011-2022 走看看