19.9. xml.dom.minidom — 最小 DOM 实现 — Python 文档
19.9. xml.dom.minidom — 最小的 DOM 实现
2.0 版中的新功能。
源代码: :source:`Lib/xml/dom/minidom.py`
xml.dom.minidom 是文档对象模型接口的最小实现,其 API 类似于其他语言中的 API。 它旨在比完整的 DOM 更简单,而且体积也小得多。 尚未精通 DOM 的用户应考虑使用 xml.etree.ElementTree 模块进行 XML 处理。
DOM 应用程序通常首先将一些 XML 解析为 DOM。 使用 xml.dom.minidom,这是通过解析函数完成的:
from xml.dom.minidom import parse, parseString
dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name
datasource = open('c:\\temp\\mydata.xml')
dom2 = parse(datasource) # parse an open file
dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')
parse() 函数可以采用文件名或打开的文件对象。
- xml.dom.minidom.parse(filename_or_file[, parser[, bufsize]])
- 从给定的输入返回一个
Document
。 filename_or_file 可以是文件名,也可以是类似文件的对象。 parser 如果给定,则必须是 SAX2 解析器对象。 此函数将更改解析器的文档处理程序并激活命名空间支持; 其他解析器配置(如设置实体解析器)必须提前完成。
如果字符串中有 XML,则可以改用 parseString() 函数:
- xml.dom.minidom.parseString(string[, parser])
- 返回表示 字符串 的
Document
。 此方法为字符串创建一个 StringIO 对象并将其传递给 parse()。
这两个函数都返回一个表示文档内容的 Document
对象。
parse() 和 parseString() 函数的作用是将 XML 解析器与“DOM 构建器”连接起来,该“DOM 构建器”可以接受来自任何 SAX 解析器的解析事件并将它们转换为 DOM 树. 函数的名称可能会产生误导,但在学习接口时很容易掌握。 文档的解析会在这些函数返回之前完成; 只是这些函数本身不提供解析器实现。
您还可以通过调用“DOM 实现”对象上的方法来创建 Document
。 您可以通过调用 xml.dom 包中的 getDOMImplementation()
函数或 xml.dom.minidom 模块来获取此对象。 使用来自 xml.dom.minidom 模块的实现将始终从 minidom 实现返回一个 Document
实例,而来自 xml.dom 的版本可能会提供一个替代实现(如果您安装了 PyXML 包 ,这很可能)。 一旦你有了一个 Document
,你就可以向它添加子节点来填充 DOM:
from xml.dom.minidom import getDOMImplementation
impl = getDOMImplementation()
newdoc = impl.createDocument(None, "some_tag", None)
top_element = newdoc.documentElement
text = newdoc.createTextNode('Some textual content.')
top_element.appendChild(text)
一旦拥有 DOM 文档对象,就可以通过其属性和方法访问 XML 文档的各个部分。 这些属性在 DOM 规范中定义。 文档对象的主要属性是 documentElement
属性。 它为您提供 XML 文档中的主要元素:包含所有其他元素的元素。 这是一个示例程序:
dom3 = parseString("<myxml>Some data</myxml>")
assert dom3.documentElement.tagName == "myxml"
当你完成一个 DOM 树时,你可以选择调用 unlink()
方法来鼓励早期清理现在不需要的对象。 unlink()
是 xml.dom.minidom 特定于 DOM API 的扩展,它呈现节点及其后代本质上是无用的。 否则,Python 的垃圾收集器最终会处理树中的对象。
19.9.1. DOM 对象
Python DOM API 的定义作为 xml.dom 模块文档的一部分给出。 本节列出了 API 和 xml.dom.minidom 之间的差异。
- Node.unlink()
- 中断 DOM 中的内部引用,以便在没有循环 GC 的 Python 版本上对其进行垃圾收集。 即使循环 GC 可用,使用它也可以更快地使大量内存可用,因此在不再需要的 DOM 对象上调用它是一种很好的做法。 这只需要在
Document
对象上调用,但可以在子节点上调用以丢弃该节点的子节点。
- Node.writexml(writer, indent=, addindent=, newl=)
将 XML 写入编写器对象。 编写器应该有一个
write()
方法来匹配文件对象接口的方法。 indent 参数是当前节点的缩进。 addindent 参数是用于当前子节点的增量缩进。 newl 参数指定用于终止换行符的字符串。对于
Document
节点,可以使用额外的关键字参数 encoding 来指定 XML 标头的编码字段。2.1 版本变更: 可选关键字参数 indent、addindent 和 newl 被添加到支持漂亮输出。
2.3 版本变更: 对于
Document
节点,可以使用额外的关键字参数 encoding 来指定 XML 标头的编码字段。
- Node.toxml([encoding])
返回 DOM 表示为字符串的 XML。
如果不带参数,XML 标头不指定编码,如果默认编码不能表示文档中的所有字符,则结果为 Unicode 字符串。 使用 UTF-8 以外的编码对此字符串进行编码可能不正确,因为 UTF-8 是 XML 的默认编码。
使用显式 encoding 1 参数,结果是指定编码的字节字符串。 建议始终指定此参数。 为了在不可表示的文本数据的情况下避免
UnicodeError
异常,应将编码参数指定为“utf-8”。在 2.3 版更改:引入了 编码 参数; 参见 writexml()。
- Node.toprettyxml(indent='\\t', newl='\\n', encoding=None)
返回文档的漂亮打印版本。 indent 指定缩进字符串,默认为制表符; newl 指定在每行末尾发出的字符串,默认为
\n
。2.1 版中的新功能。
2.3 版本变化: 引入了编码参数; 参见 writexml()。
以下标准 DOM 方法对 xml.dom.minidom 有特殊考虑:
- Node.cloneNode(deep)
- 虽然这个方法在 Python 2.0 打包的 xml.dom.minidom 版本中存在,但它被严重破坏了。 这已在后续版本中得到纠正。
19.9.2. DOM 示例
这个示例程序是一个相当现实的简单程序示例。 在这种特殊情况下,我们没有充分利用 DOM 的灵活性。
import xml.dom.minidom
document = """\
<slideshow>
<title>Demo slideshow</title>
<slide><title>Slide title</title>
<point>This is a demo</point>
<point>Of a program for processing slides</point>
</slide>
<slide><title>Another demo slide</title>
<point>It is important</point>
<point>To have more than</point>
<point>one slide</point>
</slide>
</slideshow>
"""
dom = xml.dom.minidom.parseString(document)
def getText(nodelist):
rc = []
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
rc.append(node.data)
return ''.join(rc)
def handleSlideshow(slideshow):
print "<html>"
handleSlideshowTitle(slideshow.getElementsByTagName("title")[0])
slides = slideshow.getElementsByTagName("slide")
handleToc(slides)
handleSlides(slides)
print "</html>"
def handleSlides(slides):
for slide in slides:
handleSlide(slide)
def handleSlide(slide):
handleSlideTitle(slide.getElementsByTagName("title")[0])
handlePoints(slide.getElementsByTagName("point"))
def handleSlideshowTitle(title):
print "<title>%s</title>" % getText(title.childNodes)
def handleSlideTitle(title):
print "<h2>%s</h2>" % getText(title.childNodes)
def handlePoints(points):
print "<ul>"
for point in points:
handlePoint(point)
print "</ul>"
def handlePoint(point):
print "<li>%s</li>" % getText(point.childNodes)
def handleToc(slides):
for slide in slides:
title = slide.getElementsByTagName("title")[0]
print "<p>%s</p>" % getText(title.childNodes)
handleSlideshow(dom)
19.9.3. minidom 和 DOM 标准
xml.dom.minidom 模块本质上是一个与 DOM 1.0 兼容的 DOM,具有一些 DOM 2 特性(主要是命名空间特性)。
在 Python 中使用 DOM 接口很简单。 以下映射规则适用:
- 接口通过实例对象访问。 应用程序不应实例化类本身; 他们应该使用
Document
对象上可用的创建者函数。 派生接口支持来自基本接口的所有操作(和属性),以及任何新操作。 - 操作被用作方法。 由于 DOM 仅使用 in 参数,因此参数按正常顺序(从左到右)传递。 没有可选参数。
void
操作返回None
。 - IDL 属性映射到实例属性。 为了与 Python 的 OMG IDL 语言映射兼容,还可以通过访问器方法
_get_foo()
和_set_foo()
访问属性foo
。readonly
属性不得更改; 这不是在运行时强制执行的。 - 类型
short int
、unsigned int
、unsigned long long
和boolean
都映射到 Python 整数对象。 - 类型
DOMString
映射到 Python 字符串。 xml.dom.minidom 支持字节或 Unicode 字符串,但通常会生成 Unicode 字符串。DOMString
类型的值也可能是None
,其中 W3C 的 DOM 规范允许具有 IDLnull
值。 const
声明映射到各自范围内的变量(例如xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE
); 不得更改。DOMException
目前在 xml.dom.minidom 中不受支持。 相反,xml.dom.minidom 使用标准 Python 异常,例如TypeError
和AttributeError
。NodeList
对象是使用 Python 的内置列表类型实现的。 从 Python 2.2 开始,这些对象提供了 DOM 规范中定义的接口,但在早期版本的 Python 中,它们不支持官方 API。 然而,它们比 W3C 建议中定义的接口更“Pythonic”。
以下接口在 xml.dom.minidom 中没有实现:
DOMTimeStamp
DocumentType
(在 Python 2.1 中添加)DOMImplementation
(在 Python 2.1 中添加)CharacterData
CDATASection
Notation
Entity
EntityReference
DocumentFragment
其中大部分反映了 XML 文档中对大多数 DOM 用户没有通用性的信息。
脚注
- 1
- XML 输出中包含的编码字符串应符合相应的标准。 例如,“UTF-8”有效,但“UTF8”无效。 参见 https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl 和 https://www.iana.org/assignments/character-sets /character-sets.xhtml。