zoukankan      html  css  js  c++  java
  • 【译】:lxml.etree官方文档

    本文翻译自:http://lxml.de/tutorial.html, 作者:Stefan Behnel

    这是一个关于使用lxml.etree进行XML处理的教程。它简要介绍了ElementTree API的主要概念,以及一些简单的增强功能,使你的编程更容易。

    有关API的完整参考,请参考生成的API文档

    内容:

      • 元素类

        · 元素是列表

        · 元素以属性为特征

        · 元素包含文本

        · 使用XPath查找文本

        · 树迭代

        · 序列化

      • ElementTree类

      • 从字符串和文件解析

        · fromstring()函数

        · XML()函数

        · parse()函数

        · 解析器对象

        · 增量解析

        · 事件驱动解析

      • Namespaces

      • The E-factory

      • ElementPath

     导入lxml.etree的常见方法如下:

    from lxml import etree

    如果你的代码仅使用ElementTree API,并不依赖于特定的lxml.etree的任何功能,你还可以利用下面的导入方法:

    try:
        from lxml import etree
        print("running with lxml.etree")
    except ImportError:
        try:
            #Python 2.5
            import xml.etree.cElementTree as etree
            print("running with cElementTree on Python 2.5+")
        except ImportError:
            try:
                #Python 2.5
                import xml.etree.ElementTree as etree
                print("running with ElementTree on Python 2.5+")
            except ImportError:
                try:
                    #正常的cElementTree安装
                    import cElementTree as etree
                    print("running with cElementTree")
                except ImportError:
                    try:
                        #正常的ElementTree安装
                        import elementtree.ElementTree as etree
                        print("running with ElementTree")
                    except ImportError:
                        print("Failed to import ElementTree from any known place")

    为了编写可移植代码,本教程在例子中说明了API的哪一部分是由Fredrik Lundh的ElementTree库定义的原始ElementTree API的lxml.etree的扩展。

    » 元素类

    单个元素是ElementTree API的主要的容器对象。大多数XML树功能都是通过这个类访问的。元素可以通过Element factory轻松创建:

    >>> root = etree.Element("root")

    元素的XML标签名通过tag属性访问:

    >>> print (root.tag)
    root

    元素以XML树结构组织。要添加子元素并将其添加到父元素中,可以使用append()方法:

    >>> root.append( etree.Element("child1") )

    然而,这是很常见的。有一个更短更有效的方法做到这一点:SubElement factory。它接受与Element factory相同的参数,但要求父元素作为第一个参数:

    >>> child2 = etree.SubElement(root, "child2")
    >>> child3 = etree.SubElement(root, "child3")

    要看到真正的XML,你可以序列化创建的树:

    >>> print (etree.tostring(root, pretty_print = True))
    <root>
        <child1/>
        <child2/>
        <child3/>
    </root>

    元素是列表

    为了更容易、更直接的访问这些子元素,元素尽可能地模仿python列表的行为:

    >>> child = root[0]
    >>> print (child.tag)
    child1
    
    >>> print (len(root))
    3
    
    >>> root.index(root[1])
    1
    
    >>> children = list(root)
    
    >>> for child in root:
    ...           print (child.tag)
    child1
    child2
    child3
    
    >>> root.insert(0, etree.Element("child0"))
    >>> start = root[:1]
    >>> end = root[-1:]
    
    >>> print (start[0].tag)
    child0
    >>> print (end[0].tag)
    child3

     在ElementTree 1.3和lxml 2.0之前,你还可以检查一个元素的真值,看它是否有子代,即如果子列表为空:

    if root:
        print ("The root element has children")

    这不再受支持,因为人们倾向于期待"something“被评估为True,期待元素成为"something”,它们可能有子代吗?所以很多用户惊奇的发现任何元素都会在上面的if语句中被评估为False。相反的,使用len(element)更明确,更少出错。

    >>> print (etree.iselement(root))   #测试它是否是element类型
    True
    >>> if len(root):                   #测试它是否有子代
    ...          print ("The root element has children")
    The root element has children

    还有一种重要的情况,其中lxml(2.0及以上版本)中Elements的行为偏离了列表和原始的ElementTree(1.3之前的版本或Python2.7/3.2):

    >>> for child in root:
    ...           print (child.tag)
    child0
    child1
    child2
    child3
    >>> root[0] = root[-1]
    >>> for child in root:
    ...           print (child.tag)
    child3
    child1
    child2

    在这个例子中,最后一个元素被剪切到一个不同的位置,而不是复制,即当它被放在不同的位置时,它被自动从它前一个位置移除。在列表中,对象可以同时出现在多个位置,上述分配只会将item引用复制到第一个位置,以便两者都包含相同的item。

    >>> 1 = [0, 1, 2, 3]
    >>> 1[0] = 1[-1]
    >>> 1
    [3, 1, 2, 3]

     注意在原始的ElementTree中,单个的Element对象可以位于任意数量的树中的任意数量位置,这允许与列表相同的复制操作,明显的缺点是对这种元素的修改将会适用于它出现树中的所有地方,这可能是也可能不是初衷。

    这个区别的优点是,lxml.etree中的Element总是具有一个父对象,可以通过getparent()方法进行查询。这在原始的ElementTree中是不支持的。

    >>> root is root[0].getparent()
    True

    如果要将单个元素复制到lxml.etree中的不同位置,请考虑使用Python标准库中的复制模块来创建一个独立的深层副本:

    >>> from copy import deepcopy
    
    >>> element = etree.Element("neu")
    >>> element.append( deepcopy(root[1]) )
    
    >>> print (element[0].tag)
    child1
    >>> print ([ c.tag for c in root ])
    ['child3', 'child1', 'child2']

    元素的同胞(或邻居)作为下一个和前一个元素被访问:

    >>> root[0] is root[1].getprevious()
    True
    >>> root[1] is root[0].getnext()
    True

    元素以属性为特征

    XML元素支持属性。你可以在Element factory直接创建它们:

    >>> root = etree.Element("root", interesting = "totally")
    >>> etree.tostring(root)
    b'<root interesting = "totally"/>'

     属性只是无序的name-value对,所以处理它们非常方便的方法是通过Elements的类似字典的界面:

    >>> print (root.get("interesting"))
    totally
    
    >>> print (root.get("hello"))
    None
    >>> root.set("hello", "Huhu"))
    >>> print (root.get("hello"))
    Huhu
    
    >>> etree.tostring(root)
    b'<root insteresting = "totally" hello = "Huhu"/>'
    
    >>> sorted(root.keys())
    ['hello', 'insteresting']
    
    >>> for name, value in sorted(root.items()):
    ...           print ('%s = %r' % (name, value))
    hello = 'Huhu'
    interesting = 'totally'

    对于你想查找item或其他原因来获取一个'real'类似字典对象的情况,例如传递给它,你可以使用attrib属性:

    >>> attributes = root.attrib
    
    >>> print (attributes["interesting"])
    totally
    >>> print (attributes.get("no-such-attribute"))
    None
    
    >>> attributes["Hello"] = "Guten Tag"
    >>> print (attributes["hello"])
    Guten Tag
    >>> print (root.get("hello"))
    Guten Tag

    注意attrib是由Element本身支持的类似dict的对象。这意味着对元素的任何修改都反映在属性中,反之亦然。这也意味着,只要一个元素的attrib在使用,XML树就活跃在内存中。要获取不依赖XML树的属性的独立快照,将其复制到dict中:

    >>> d = dict(root.attrib)
    >>> sorted(d.items())
    [('hello', 'Guten Tag'), ('insteresting', 'totally')]

    元素包含文本

    元素可以包含文本:

    >>> root = etree.Element("root")
    >>> root.text = "TEXT"
    
    >>> print (root.text)
    TEXT
    
    >>> etree.tostring(root)
    b'<root>TEXT</root>'

     在许多XML文档(以数据为中心的文档)中,这是唯一可以找到文本的地方。它由叶子标签封装在树层次结构的底部。

    然而,如果XML用于标记的文本文档,例如(X)HTML,文本也可以出现在不同元素之间,就在树的中间:

    <html><body>Hello</br>World</body></html>

    这里,</br>标签由文本环绕。这通常被称为文本样式或混合内容XML。元素通过尾部属性来支持它。它包含直接跟随元素的文本,直到XML树中的下一个元素:

    >>> html = etree.Element("html")
    >>> body = etree.SubElement(html, "body")
    >>> body.text = "TEXT"
    
    >>> etree.tostring(html)
    b'<html><body>TEXT</body></html>'
    
    >>> br = etree.SubElement(body, "br")
    >>> etree.tostring(html)
    b'<html><body>TEXT<br/></body></html>'
    
    >>> br.tail = "TAIL"
    >>> etree.tostring(html)
    b'<html><body>TEXT<br/>TAIL</body></html>'

    两个属性 .text和 .tail足以表示XML文档中的任何文本内容。这样,除了Element类之外,ElementTree API不需要任何特殊的文本节点,它往往会得到一些方法(正如你从传统的的DOM API中知道的那样)。

    然而,有些情况下尾部文本也会妨碍。例如,当你从树中序列化一个元素时,你并不总是希望在结果中显示尾部文本(尽管你仍然希望其子代码的尾部文本)。为此,tostring()函数接受关键字参数with_tail

    >>> etree.tostring(br)
    b'<br/>TAIL'
    >>> etree.tostring(br, with_tail=False) # lxml.etree only!
    b'<br/>'

    如果你想读的只有文字,即没有任何中间变量,你必须递归串联所有文字和以正确的顺序属性。再次使用tostring()函数来救援,这次使用method关键字:

    >>> etree.tostring(html, method="text")
    b'TEXTTAIL'
  • 相关阅读:
    兼容ie6浏览器窗口四角固定背景代码
    实用的js判断浏览器类型及版本
    测试
    C#动态获取鼠标位置的颜色
    对指定的网页进行截图
    C#中使用 SendMessage 向非顶端窗体发送组合键
    ProtelDXP练习作品51单片机最小系统
    对非顶端窗口截图
    C#直接操作并口
    单片机实现的数字钟
  • 原文地址:https://www.cnblogs.com/my_captain/p/7490292.html
Copyright © 2011-2022 走看看