一切内容都是摘抄,主要是便于回忆和鼓励自己不要间断,更详细内容请见原帖地址:
《深入 python3 》中文版
http://woodpecker.org.cn/diveintopython3/index.html
12.1. 概述
12.2. 5分钟XML速成
XML是一种描述层次结构化数据的通用方法。XML文档包含由起始和结束标签(tag)分隔的一个或多个元素(element)。
元素可以嵌套到任意层次。位于foo中的元素bar可以被称作其子元素。
XML文档中的第一个元素叫做根元素(root element)。并且每份XML文档只能有一个根元素。以下不是一个XML文档,因为它存在两个“根元素”。
元素可以有其属性(attribute),它们是一些名字-值(name-value)对。属性由空格分隔列举在元素的起始标签中。一个元素中属性名不能重复。属性值必须用引号包围起来。单引号、双引号都是可以。
如果元素有多个属性,书写的顺序并不重要。元素的属性是一个无序的键-值对集,跟Python中的列表对象一样。另外,元素中属性的个数是没有限制的。
表达空元素有一种简洁的方法。通过在起始标签的尾部添加/字符,我们可以省略结束标签。
就像Python函数可以在不同的模块(modules)中声明一样,也可以在不同的名字空间(namespace)中声明XML元素。XML文档的名字空间通常看起来像URL。我们可以通过声明xmlns来定义默认名字空间。名字空间声明跟元素属性看起来很相似,但是它们的作用是不一样的。
也可以通过xmlns:prefix声明来定义一个名字空间并取其名为prefix。然后该名字空间中的每个元素都必须显式地使用这个前缀(prefix)来声明
对于XML解析器而言,以上两个XML文档是一样的。名字空间 + 元素名 = XML标识。前缀只是用来引用名字空间的,所以对于解析器来说,这些前缀名(atom:)其实无关紧要的。名字空间相同,元素名相同,属性(或者没有属性)相同,每个元素的文本内容相同,则XML文档相同
最后,在根元素之前,字符编码信息可以出现在XML文档的第一行。(这里存在一个两难的局面(catch-22),直观上来说,解析XML文档需要这些编码信息,而这些信息又存在于XML文档中,如果你对XML如何解决此问题有兴趣,请参阅XML规范中 F 章节)
12.3. Atom Feed的结构
summary 元素中有这篇文章的概要性描述。(还有一个元素这里没有展示出来,即content ,我们可以把整篇文章的内容都放在里边。)当前样例中,summary 元素含有一个Atom特有的type='html' 属性,它用来告知这份概要为HTML 格式,而非纯文本。这非常重要,因为概要内容中包含了HTML 中特有的实体(— 和… ),它们不应该以纯文本直接显示,正确的形式应该为“—”和“…”。
12.4. 解析XML
>>>
import xml.etree.ElementTree as etree
①
>>>
tree = etree.parse('examples/feed.xml')
②
>>>
root = tree.getroot()
③
>>>
root
④
<Element {http://www.w3.org/2005/Atom}feed at cd1eb0>
- ElementTree属于Python标准库的一部分,它的位置为
xml.etree.ElementTree。 parse()函数是ElementTree库的主要入口,它使用文件名或者流对象 作为参数。parse()函数会立即解析完整个文档。如果内存资源紧张,也可以增量式地解析XML 文档parse()函数会返回一个能代表整篇文档的对象。这不是 根元素。要获得根元素的引用可以调用getroot()方法。- 如预期的那样,根元素即
http://www.w3.org/2005/Atom名字空间中的feed。该字符串表示再次重申了非常重要的一点:XML 元素由名字空间和标签名(也称作本地名(local name) )组成。这篇文档中的每个元素都在名字空间Atom中,所以根元素被表示为{http://www.w3.org/2005/Atom}feed。
ElementTree使用{namespace}localname来表达XML元素。我们将会在ElementTree的API中多次见到这种形式。
12.4.1. 元素即列表
根元素的“长度”即子元素的个数。
我们可以像使用迭代器一样来遍历其子元素
12.4.2. 属性即字典
XML不只是元素的集合;每一个元素还有其属性集。一旦获取了某个元素的引用,我们可以像操作Python的字典一样轻松获取到其属性。
12.5. 在XML文档中查找结点
但是许多情况下我们需要找到XML中特定的元素。Etree也能完成这项工作。
每个元素 — 包括根元素及其子元素 — 都有findall()方法。它会找到所有匹配的子元素。但是为什么没有看到任何结果呢?也许不太明显,这个查询只会搜索其子元素。
为了方便,对象tree(调用etree.parse()的返回值)中的一些方法是根元素中这些方法的镜像。在这里,如果调用tree.getroot().findall(),则返回值是一样的。
find()方法用来返回第一个匹配到的元素。当我们认为只会有一个匹配,或者有多个匹配但我们只关心第一个的时候,这个方法是很有用的。
可逮住你了,在这里find()方法非常容易被误解。在布尔上下文中,如果ElementTree元素对象不包含子元素,其值则会被认为是False(即如果len(element)等于0)。这就意味着if element.find('...')并非在测试是否find()方法找到了匹配项;这条语句是在测试匹配到的元素是否包含子元素!想要测试find()方法是否返回了一个元素,则需使用if element.find('...') is not None。
>>> all_links = tree.findall('//{http://www.w3.org/2005/Atom}link')
//{http://www.w3.org/2005/Atom}link与前一样例很相似,除了开头的两条斜线。这两条斜线告诉findall()方法“不要只在直接子元素中查找;查找的范围可以是任意嵌套层次”。
12.6. 深入lxml
lxml是一个开源的第三方库,以流行的libxml2 解析器为基础开发。提供了与ElementTree完全兼容的API,并且扩展它以提供了对XPath 1.0的全面支持,以及改进了一些其他精巧的细节。提供Windows的安装程序;Linux用户推荐使用特定发行版自带的工具比如yum或者apt-get从它们的程序库中安装预编译好了的二进制文件。要不然,你就得手工安装他们了。
对于大型的XML文档,lxml明显比内置的ElementTree快了许多。如果现在只用到了ElementTree的API,并且想要使用其最快的实现(implementation),我们可以尝试导入lxml,并且将内置的ElementTree作为备用。
>>> tree.findall('//{http://www.w3.org/2005/Atom}*[@href]')
这一句在整个文档范围内搜索名字空间Atom中具有href属性的所有元素。在查询语句开头的//表示“搜索的范围为整个文档(不只是根元素的子元素)。” {http://www.w3.org/2005/Atom}指示“搜索范围仅在名字空间Atom中。” * 表示“任意本地名(local name)的元素。” [@href]表示“含有href属性。”
>>> tree.findall("//{http://www.w3.org/2005/Atom}*[@href='http://diveintomark.org/']")
该查询找出所有包含href属性并且其值为http://diveintomark.org/的Atom元素。
>>> tree.findall('//{NS}author[{NS}uri]'.format(NS=NS))
在简单的字符串格式化后(要不然这条复合查询语句会变得特别长),它搜索名字空间Atom中包含uri元素作为子元素的author元素。该条语句只返回了第一个和第二个entry元素中的author元素。最后一个entry元素中的author只包含有name属性,没有uri。
>>> entries = tree.xpath("//atom:category[@term='accessibility']/..", namespaces=NSMAP)
这就是一个XPath查询请求。这个XPath表达式目的在于搜索category元素,并且该元素包含有值为accessibility的term属性。但是那并不是查询的结果。请看查询字符串的尾端;是否注意到了/..这一块?它的意思是,“然后返回已经找到的category元素的父元素。”所以这条XPath查询语句会找到所有包含作为子元素的条目。
>>> entry.xpath('./atom:title/text()', namespaces=NSMAP)
XPath表达式并不总是会返回一个元素列表。技术上说,一个解析了的XML文档的DOM模型并不包含元素;它只包含结点(node)。依据它们的类型,结点可以是元素,属性,甚至是文本内容。XPath查询的结果是一个结点列表。当前查询返回一个文本结点列表:title元素(atom:title)的文本内容(text()),并且title元素必须是当前元素的子元素(./)。
以下的内容不看了,用到时候再说吧
本文介绍如何使用Python解析XML文档,涵盖基本概念、ElementTree库的使用及lxml库的高级功能。通过实例演示如何查找、提取XML数据。
47

被折叠的 条评论
为什么被折叠?



