lxml Element类相关的介绍

来源:互联网 发布:淘宝下载到桌面 编辑:程序博客网 时间:2024/06/07 21:26

Element class

用lxml首先我们要导入相关库

>>>from lxml import etree

创建一个root节点

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

看看root是什么

>>> print root<Element root at 0x3060108> #是Element类>>> type(root)<type 'lxml.etree._Element'> 

打印节点的名字

>>>print(root.tag)root

创建一个子节点并添加到父节点中

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

另一种创建子节点并添加到节点中的方式

>>> etree.SubElement(root,"child2")<Element child2 at 0x2ef7b48>>>> etree.SubElement(root,"child3")<Element child3 at 0x305b208>

看看现在root都有什么内容了

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

Elements are lists (Element类是python里的列表)

为了使获取子节点更直接和容易,elements模仿尽可能的模仿了正常python 列表的表现行为
我的理解为把Element 下的 SubElement组成的列表

#下标操作>>> root[0].tag'child1'#负数下标>>> root[-1].tag'child3'#列表的方法>>> len(root)3>>> children = list(root)>>> children[<Element child1 at 0x305b208>, <Element child2 at 0x2f5eec8>, <Element child3 at 0x2f5e088>]#列表的迭代>>> for child in root:    print child.tagchild1child2child3#列表的插入>>> root.insert(0,etree.Element('child0'))>>> len(root)4#列表的分片>>> start = root[:1]>>> start[<Element child0 at 0x2f5eb08>]#列表的负数分片>>> end = root[-1:]>>> end[<Element child3 at 0x2f5e088>]>>> print start[0].tagchild0>>> print end[0].tagchild3

直到ElementTree1.3和lxml2.0,你可以用bool值 来测试Element有没有子节点

#这样作会得到一个警告>>> if root:    print 1Warning (from warnings module):  File "__main__", line 2FutureWarning: The behavior of this method will change in future versions. Use specific 'len(elem)' or 'elem is not None' test instead.1

注意

#创建一个节点pa = etree.Element('p')#节点p里的文本为something texta.text = "something text"# "<p>something text"res = bool(a) #这里会是Truelength = len(a) #这里length的长度为0

这会引起人们的惊讶和疑惑,因此,引入etree.iselement()方法

>>> etree.iselement(root)True>>> if len(root):    print "The root element has child"The root element has child

下面是关于复制的特性

>>> for child in root:    print child.tagchild0child1child2child3>>> root[0] = root[-1] #这里会把列表的最后一个元素移到到第一个,而不是简单的复制>>> for child in root:    print child.tagchild3child1child2

我们可能会对移动这个特性感到疑惑,来作一个关于list的实验

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

如果你想复制一个节点到别的地方,我们要用深复制copy.deepcopy()方法

>>> from copy import deepcopy>>> root.insert(0,deepcopy(root[-1]))>>> for child in root:    print child.tagchild2child3child1child2

获取父节点
获取前一个节点
获取下一个节点

>>> root[0].getparent().tag'root'>>> root[1].getprevious().tag'child2'>>> root[0].getnext().tag'child3'

为节点添加数据
Elements 用python的字典表示节点的属性

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

属性是一些无序的键值对,我们可以用Elements的类字典接口来处理这些属性

>>> root.get("interesting")'totally'>>> root.get("hello")  #None>>> root.set("hello", "huhu")>>> root.get("hello")'huhu'>>> etree.tostring(root)'<root interesting="totally" hello="huhu"/>'>>> root.keys()['interesting', 'hello']>>> root.items()[('interesting', 'totally'), ('hello', 'huhu')]

因为Element[index]等重载方法表示的是list,如果想要得到一个真正的类字典对象,可以使用Element.attrib属性

#获取对Elements对象属性的引用>>> attributes = root.attrib>>> attributes{'interesting': 'totally', 'hello': 'huhu'}#可以看到attributes并不是一个真正的字典,只是个类字典对象>>> type(attributes)<type 'lxml.etree._Attrib'>>>> attributes["hello"]'huhu'>>> attributes.get("hello")'huhu'>>> attributes["hello"] = "heihei"对attributes的修改会影响到Elements对象的属性字典,因为其是一个引用>>> etree.tostring(root)'<root interesting="totally" hello="heihei"/>'

Elements包含text属性

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

在许多xml文档中,这是唯一出现文本的地方,在节点的最深处,并被标签包围

<a>    <b>        <c>some text</c>    </b></a>

但是如果是(x)html,情况就不一样了如相:

<html><body>Hello<br/>World</body></html><!-- 或者这样 --><div>text<span>ohter text</span>text else</div>

如上所示,br 标签两边都是文本我们该怎样获取World呢,我们先构造这样的元素

>>> html = etree.Element("html")>>> body = etree.Element("body")>>> br = etree.Element("br")>>> >>> body.text="Hello">>> body.append(br)#可能这里你看不明白,这里的意思是在br的尾部加上"World">>> br.tail = "World">>> html.append(body)>>> etree.tostring(html)'<html><body>Hello<br/>World</body></html>'

Elements有了.text 和 .tail 两个表示文本的属性就足够表现任何文本在xml中,但是这样的特性也会造成问题如

>>> etree.tostring(br)'<br/>World'

如果你不想Elements带上尾巴你可以这样作

>>> etree.tostring(br,with_tail=False)'<br/>'

如果你不想要Elements的标签,而想要Elements的 .text 和 .tail你可以这样作

# 提取所有Elements的所有文本,不显示标签>>> etree.tostring(html,method="text")'HelloWorld'

Elements树的迭代
如果你想递归的迭代Elements,你可以使用Elements.iter()方法,它会根据文档的顺序产生迭代器

>>> root = etree.Element("root")>>> child1 = etree.SubElement(root,"child")>>> child1_son = etree.SubElement(child1,"son")>>> child1_son.text = "child1 son">>> child2 = etree.SubElement(root,"child")>>> another = etree.SubElement(root,"anothor").text = "Child 3">>> print etree.tostring(root, pretty_print=True)<root>  <child>    <son>child1 son</son>  </child>  <child/>  <anothor>Child 3</anothor></root>>>> for element in root.iter():    print "%s - %s" % (element.tag, element.text)root - Nonechild - Noneson - child1 sonchild - Noneanothor - Child 3

如果你想过滤一些想要的标签,你可以

for element in root.iter("anothor"):    print element.tag, element.text

在lxml3.0中,你可以放入多个过滤

>>> for element in root.iter("anothor", "son"):    print element.text, element.tagchild1 son sonChild 3 anothor

默认的,迭代器会遍历所有节点,包括处理命令,注释和,实体实例。如果你想只返回Elements objects

>>> root.append(etree.Entity("#234"))>>> root.append(etree.Comment("some comment"))>>> for element in root.iter():    if isinstance(element.tag, basestring):        print "%s - %s" % (element.tag, element.text)    else:        print "SPECIAL : %s - %s" % (element, element.text)root - Nonechild - Noneson - child1 sonchild - Noneanothor - Child 3SPECIAL : &#234; - &#234;SPECIAL : <!--some comment--> - some comment>>> for element in root.iter(tag=etree.Element):    print "%s - %s" % (element.tag, element.text)root - Nonechild - Noneson - child1 sonchild - Noneanothor - Child 3>>> for element in root.iter(tag=etree.Entity):    print element.text&#234;>>> for element in root.iter(tag=etree.Comment):    print element.textsome comment

输出通常使用tostring()方法返回字符串,或者ElementTree.write()方法写入一个文件,类文件对象,或者URL。这两个方法都接受同样的参数:像pretty_print (美化)encoding(编码)

print etree.tostring(root, xml_declaration=True, encoding="utf-8")<?xml version='1.0' encoding='utf-8'?><root><a><b/></a></root>

在lxml2.0之后,

>>> from lxml import etree>>> root = etree.XML('<html><head/><body><p>Hello<br/>World</p></body></html>')>>> etree.tostring(root)'<html><head/><body><p>Hello<br/>World</p></body></html>'>>> etree.tostring(root,method="html")'<html><head></head><body><p>Hello<br>World</p></body></html>'>>> etree.tostring(root,method="text")'HelloWorld'>>> etree.tostring(root,method="xml")'<html><head/><body><p>Hello<br/>World</p></body></html>'>>> print etree.tostring(root, method="html")<html><head></head><body><p>Hello<br>World</p></body></html>>>> print etree.tostring(root, method="html",pretty_print=True)<html><head></head><body><p>Hello<br>World</p></body></html>>>> 
0 0