Size: 14773
Comment:
|
Size: 15985
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 76: | Line 76: |
1. `e10.16, (2)`:'''However,'''…… (./) '''然而,'''…… 1. `e10.16, (3)`:每个节点都有一个 nodeType 属性,它可以是'''元素节点, 文本节点, 注释节点,或者任意数量的其它值'''。可能值的完整列表在xml.dom包的 __init__.py 文件中。('''关于包更多的,参见9.2节, “包”。)但你只是对元素节点有兴趣,所以你可以过滤出一个列表,其中只包含 nodeType 是'''元素节点'''的节点。[[BR]] (./) 每个节点都有一个 nodeType 属性,它可以是'''ELEMENT_NODE, TEXT_NODE, COMMENT_NODE,或者其它值'''。可能值的完整列表在 xml.dom 包的 __init__.py 文件中。('''关于包的介绍''',参见9.2节, “包”。)但你只是对元素节点有兴趣,所以你可以过滤出一个列表,其中只包含 nodeType 是'''ELEMENT_NODE'''的节点。[[BR]] 1. `e10.16, (4)`:……将会是 p 元素的一个列表,'''并且''' chosen 将以被赋予其中的一个确切值'''而结束''',而这个值是'''随即'''选择的。[[BR]] (./) ……将会是 p 元素的一个列表,'''而''' chosen 将被赋予其中的某一个值,而这个值是'''随机'''选择的。 |
7-29<X10>kpg.xml 脚本和流
- “接收……作为参数”一律改为“接受……作为参数”
本章标题:Scrips 和 Streams
脚本和流
抽象输入源
Para 1:Python 的最强大力量之一是它的动态绑定,并且动态绑定最强大的用法之一是类文件(file-like)对象。BR
Python 的最强大力量之一是它的动态绑定,而动态绑定最强大的用法之一是类文件(file-like)对象。
例10.1上, Para -2:只要你将一个类文件对象传递给函数,函数只是调用对象的 read 方法,函数可以处理任何类型的输入源,而不需要处理每种类型的特定代码。BR
只要你将一个类文件对象传递给函数,函数只是调用对象的 read 方法,就可以处理任何类型的输入源,而不需要为处理每种类型分别编码。
例10.1上, Para -1:你可能纳闷过这和 XML 处理有什么关系,……
你可能会纳闷,……
e10.1, (3):确保处理完成
文件后调用 close 方法。
e10.2up:哦,所有这些看上去象是在浪费大量的时间。毕竟,你已经看过 minidom.parse 可以只接收文件名,并自动执行所有打开文件和关闭无用文件的行为。不错,如果你知道正要解析的是一个本地文件,你可以传递文件名而且 minidom.parse 可以足够聪明的做正确的事情™,这一切都不会有问题。但是请注意,使用类文件分析直接从Internet上来的 XML 文档是多么相似和容易的事情!BR
哦,所有这些看上去像是在浪费大量的时间。毕竟,你已经看到,minidom.parse 可以只接收文件名,并自动执行所有打开文件和关闭无用文件的行为。不错,如果你知道正要解析的是一个本地文件,你可以传递文件名而且 minidom.parse 可以足够聪明地做正确的事情(Do The Right Thing™),这一切都不会有问题。但是请注意,使用类文件,会使分析直接从 Internet 上来的 XML 文档变得多么相似和容易!BR
我就纳闷了,怎么“做正确的事情”也成了 trademark。顺便加了个注释
这是一部著名的电影。——译注
e10.2, (1):
正如在前一章中所看到的,……
e10.2, (4):By the way, this URL is real, and it really is XML. It's an XML representation of the current headlines on Slashdot, a technical news and gossip site.BR 顺便提一句,这个 URL 是真实的,它真的是一个 XML。它是Slashdot站点(这是一个技术新闻和随笔站点)上当前标题的 XML 表示。BR
顺便提一句,这个 URL 是真实的,它真的是一个 XML。它是 Slashdot 站点(一个技术新闻和随笔站点)上当前新闻提要的 XML 表示。
e10.3down:OK,所以你可以使用 minidom.parse 函数来解析本地文件和远端 URL,但对于解析字符串,你使用……一个不同的函数。BR
好吧,所以你可以使用 minidom.parse 函数来解析本地文件和远端 URL,但对于解析字符串,你使用……另一个函数。
e10.4up:如果有一个方法可以把字符串转换成类文件对象,那么你可以只把
这个对象传递给 minidom.parse 就可以了。
只要
e10.4, (1):StringIO 模块只包含了单个
类,也叫 StringIO,它允许你将一个字符串转换为一个类文件对象。这个
StringIO 类在创建实例的时候接收字符串作为参数。
一个
e10.4, (4):任何时候,read 都将返回字符串的未读剩余
部分。
e10.5, (1):……它将调用对象的 read 方法并高兴的开始解析,绝不会知道它的输入源源
自一个硬编码的字符串。
e10.5down:那么现在你知道了如何使用单个
函数,minidom.parse,来解析一个保存在 web 页面上、本地文件中或硬编码字符串中的 XML 文档。
同一个
e10.6, (1):……source 是某种类型的字符串;它可能是一个 URL(例如 'http://slashdot.org/slashdot.rdf' ),一个本地文件的完整或者部分路径名(例如 'binary.xml'),或者是一个包含了需要解析
XML 数据的字符串。待解析
e10.6, (2):This is actually elegant in the sense that, if urllib ever supports new types of URLs in the future, you will also support them without recoding.BR 这里通过强制方式进行:尝试把它当作一个 URL 打开并静静地忽略打开非 URL 引起的错误。感觉上
这样做非常好,因为如果 urllib 将来支持更多的 URL 类型,不用重新编码就可以支持它们。
e10.6, (3):再一次,你不用做任何特别的事来检查 source 是否是一个有效的文件名(总之在不同的平台上,判断文件名有效性的规则变化很大,那么不管怎样做都可能会判断错)。BR
再一次,你不用做任何特别的事来检查 source 是否是一个有效的文件名(在不同的平台上,判断文件名有效性的规则变化很大,因此不管怎样做都可能会判断错)。
e10.6, (4):到这里,你需要假设 source 是一个其中有硬编码数据的字符串(因为没有什么可以判断的了),所以你可以使用 StringIO 从中创建一个类文件对象并将它返回。(实际上,由于使用了 str 函数,所以 source 没有必要一定是字符串;它可以是任何对象,你可以使用它的字符串表示形式,通过它的定义的 __str__ 特殊方法。)
到这里,你需要假设 source 是一个其中有硬编码数据的字符串(因为没有别的可以判断的了),所以你可以使用 StringIO 从中创建一个类文件对象并将它返回。(实际上,由于使用了 str 函数,所以 source 没有必要一定是字符串;它可以是任何对象,你可以使用它的字符串表示形式,只要定义了它的 __str__ 专用方法。)
e10.6down:……构造一个函数,接收一个指向 XML 文档的 source,而且无需知道这个 source 的含义,并
解析它。
然后
标准输入、输出和错误
Para 2:……当你 print 某些东西时,结果前往 stdout 管道;当你的程序崩溃并打印出调试信息(类似于
Python 中的
traceback(错误跟踪))的时候,信息前往 stderr 管道。
例如
e10.8, (1):正如
在例 6.9, “简单计数”中看到的,……
e10.8, (3):像 stdout
,stderr 并不为你添加硬回车;如果需要,要自己加上。
和 stdout 一样
e10.8down:……然而,它们仍然是类文件对象,并且你可以将其它任何文件或者类文件对象赋值给它们来重定向它们的输出。BR
然而,它们仍然是类文件对象,因此你可以将其它任何(类)文件对象赋值给它们来重定向其输出。
e10.9:在 Windows 上,你可以使用 type 来代替 cat 显示文件的内容。BR
在 Windows 上,你要使用 type 来代替 cat 显示文件的内容。
e10.9, (4):将所有后续的输出重定向到刚才打开的新文件上。BR
所有后续的输出都会被重定向到刚才打开的新文件上。
e10.9, (5):这样只会将输出结果“printed
”到日志文件中;……
打印
e10.10up:重定向 stderr 以完全相同的方式进行,用 sys.stderr 代替 sys.stdout。BR
重定向 stderr 以完全相同的方式进行,只要把 sys.stdout 改为 sys.stderr。
e10.10, (4):Also note that you're not explicitly closing your log file, nor are you setting stderr back to its original value. This is fine, since once the program crashes (because of the exception), Python will clean up and close the file for us, and it doesn't make any difference that stderr is never restored, since, as I mentioned, the program crashes and Python ends. Restoring the original is more important for stdout, if you expect to go do other stuff within the same script afterwards.BR 还要注意你既没有显式关闭日志文件,也没有将 stderr 设回最初的值。这样挺好,因为一旦程序崩溃(由于引发的异常),Python 将替我们清理并关闭文件,这和永远不恢复 stderr 不会造成什么不同,因为,我提到过,一旦程序崩溃,则 Python 结束。如果你希望在同一个脚本的后面去做其它的事情,恢复初始值对 stdout 更为重要。BR
还要注意你既没有显式关闭日志文件,也没有将 stderr 设回最初的值。这样挺好,因为一旦程序崩溃(由于引发的异常),Python 将替我们清理并关闭文件,因此永远不恢复 stderr 不会造成什么影响。然而对于 stdout,恢复初始值相对更为重要——你可能会在后面再次操作标准输出。
原文比较长,所以 Mark 反复强调了程序崩溃后 Python 的行为。译文相对简洁,就没有这个必要了。
e10.11up:向标准错误写入错误信息是很常见的,所以有一种较快的语法可以立刻信息导出
。
导出信息
e10.11, (1):This shorthand syntax of the print statement can be used to write to any open file, or file-like object. In this case, you can redirect a single print statement to stderr without affecting subsequent print statements. print 语句的快捷语法可以用于向任何打开的文件写入,或者是类文件对象。在这种情况下,你可以将单个 print 语句重定向到 stderr 而且不用影响后面的 print 语句。BR
print 语句的快捷语法可以用于写入任何打开的文件(或者是类文件对象)。在这里,你可以将单个 print 语句重定向到 stderr 而且不用影响后面的 print 语句。
in this case 指上文的那一行语句。
e10.11down:标准输出,另一方面,只是一个只读文件对象,它表示从前一个程序到这个程序的数据流。这个对于老的 Mac OS 用户和 Windows 用户可能不太容易理解,除非你受到过 MS-DOS 命令行的影响。它工作的方式是你可以在单个命令行中构造一个命令的链,……BR
另一方面,标准输入是一个只读文件对象,它表示从前一个程序到这个程序的数据流。这个对于老的 Mac OS 用户和 Windows 用户可能不太容易理解,除非你受到过 MS-DOS 命令行的影响。在 MS-DOS 命令行中,你可以使用一行指令构造一个命令的链,……
e10.12, (3):该处打印 binary.xml 的内容,但是“|”字符,称为“管道”符,说明内容不会打印到屏幕上。而且,它们会成为下一个命令的标准输入,在这个例子中是你调用的 Python 脚本。
该处打印 binary.xml 的内容,但是“|”字符,称为“管道”符,说明内容不会打印到屏幕上;它们会成为下一个命令的标准输入,在这个例子中是你调用的 Python 脚本。
e10.12, (4):但是想想这里的扩展性。代替cat binary.xml,你可以通过运行一个脚本动态生成语法,然后你可以通过管道将它导入你的脚本。它可以来源于任何地方:数据库,或者是生成语法的元脚本,或者其他。你根本不需要修改你的 kgp.py 脚本就可以混合使用这个功能。BR
但是想想这里的扩展性。让我们把 cat binary.xml 换成别的什么东西——例如运行一个脚本动态生成语法——然后通过管道将它导入你的脚本。它可以来源于任何地方:数据库,或者是生成语法的元脚本,或者其他。你根本不需要修改你的 kgp.py 脚本就可以并入这个功能。
e10.13, (1):……所有你要做的就是在函数的开始加入 3 行代码来检测源是否是“-”;如果是,返回 sys.stdin。实际上,that's it!
就这么简单!
查询缓冲节点
本节标题:缓冲节点查询
查询缓冲节点
Para 1:kgp.py 使用了多种技巧,对你进行 XML 处理而言它们或许有用。第一个就是,使用输入文档的结构稳定特征来构建节点缓冲。BR
kgp.py 使用了多种技巧,在你进行 XML 处理时,它们或许能派上用场。第一个就是,利用输入文档的结构稳定特征来构建节点缓冲。
Para 2:……每个 ref 包含了一个或者多个 p 元素,p 元素可以包含很多不同的东西,包括 xref。无论何时你遇到一个 xref,都可以通过相同的 id 属性找到相对应的 ref 元素,并选择 ref 元素的子元素之一进行解析。BR
……每个 ref 包含了一个或多个 p 元素,p 元素则可以包含很多不同的东西,包括 xref。对于每个 xref,你都能找到相对应的 ref 元素(它们具有相同的 id 属性),然后选择 ref 元素的子元素之一进行解析。
Para 3:如何构建语法:为最小的片段定义 ref 元素,然后通过 xref 定义“包含”第一个 ref 元素的 ref 元素,等等。然后,解析“最大的”引用并跟在每个 xref 后面,最后输出真实的文本。BR
语法的构建方式如下:先为最小的片段定义 ref 元素,然后使用 xref 定义“包含”第一个 ref 元素的 ref 元素,等等。然后,解析“最大的”引用并跟着 xref 跳来跳去,最后输出真实的文本。
e10.14, (2):……返回所有特定名称元素的一个列表。你可以很容易地得到所有 ref 元素的一个列表,然后仅仅是
遍历这个列表。
查找节点的直接子节点
e10.16, (2):However,……
然而,……
e10.16, (3):每个节点都有一个 nodeType 属性,它可以是元素节点, 文本节点, 注释节点,或者任意数量的其它值。可能值的完整列表在xml.dom包的 init.py 文件中。(关于包更多的,参见9.2节, “包”。)但你只是对元素节点有兴趣,所以你可以过滤出一个列表,其中只包含 nodeType 是元素节点的节点。BR
每个节点都有一个 nodeType 属性,它可以是ELEMENT_NODE, TEXT_NODE, COMMENT_NODE,或者其它值。可能值的完整列表在 xml.dom 包的 init.py 文件中。(关于包的介绍,参见9.2节, “包”。)但你只是对元素节点有兴趣,所以你可以过滤出一个列表,其中只包含 nodeType 是ELEMENT_NODE的节点。BR
e10.16, (4):……将会是 p 元素的一个列表,并且 chosen 将以被赋予其中的一个确切值而结束,而这个值是随即选择的。BR
……将会是 p 元素的一个列表,而 chosen 将被赋予其中的某一个值,而这个值是随机选择的。
根据节点类型创建不同的处理器
处理命令行参数
全部放在一起