xml.dom.minidom
— 最小 DOM 实现¶
xml.dom.minidom
是文档对象模型接口的最小实现,其 API 与其他语言中的类似。它旨在比完整 DOM 更简单,也显著更小。不熟悉 DOM 的用户应考虑使用 xml.etree.ElementTree
模块进行 XML 处理。
备注
如果您需要解析不受信任或未经身份验证的数据,请参阅 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=None, bufsize=None)¶
从给定输入返回一个
Document
。filename_or_file 可以是文件名,也可以是类文件对象。parser(如果给定)必须是 SAX2 解析器对象。此函数将更改解析器的文档处理程序并激活命名空间支持;其他解析器配置(如设置实体解析器)必须事先完成。
如果您有一个包含 XML 的字符串,您可以使用 parseString()
函数代替
- xml.dom.minidom.parseString(string, parser=None)¶
返回表示 string 的
Document
。此方法为字符串创建一个io.StringIO
对象,并将其传递给parse()
。
这两个函数都返回一个表示文档内容的 Document
对象。
parse()
和 parseString()
函数的作用是将 XML 解析器与“DOM 构建器”连接起来,该构建器可以接受来自任何 SAX 解析器的解析事件,并将其转换为 DOM 树。这些函数的名称可能具有误导性,但在学习接口时很容易理解。文档的解析将在这些函数返回之前完成;这些函数只是不提供解析器实现本身。
您也可以通过调用“DOM 实现”对象上的方法来创建 Document
。您可以通过调用 xml.dom
包中的 getDOMImplementation()
函数或 xml.dom.minidom
模块来获取此对象。一旦您拥有 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 的垃圾回收器最终会处理树中的对象。
参见
- 文档对象模型 (DOM) 级别 1 规范
xml.dom.minidom
支持的 W3C DOM 推荐标准。
DOM 对象¶
Python 的 DOM API 定义作为 xml.dom
模块文档的一部分提供。本节列出了 API 与 xml.dom.minidom
之间的差异。
- Node.unlink()¶
断开 DOM 内部引用,以便在没有循环 GC 的 Python 版本上进行垃圾回收。即使循环 GC 可用,使用此方法也可以更早地释放大量内存,因此在不再需要 DOM 对象时立即调用此方法是一个好习惯。这只需在
Document
对象上调用,但可以在子节点上调用以丢弃该节点的子节点。您可以通过使用
with
语句来避免显式调用此方法。当with
块退出时,以下代码将自动解除 dom 的链接with xml.dom.minidom.parse(datasource) as dom: ... # Work with dom.
- Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)¶
将 XML 写入 writer 对象。writer 接收文本而不是字节作为输入,它应该有一个与文件对象接口匹配的
write()
方法。indent 参数是当前节点的缩进。addindent 参数是用于当前节点的子节点的增量缩进。newl 参数指定用于终止换行的字符串。对于
Document
节点,可以使用额外的关键字参数 encoding 来指定 XML 头的编码字段。同样,显式声明 standalone 参数会导致将独立文档声明添加到 XML 文档的序言中。如果值设置为
True
,则添加standalone="yes"
,否则将其设置为"no"
。不声明该参数将从文档中省略该声明。在 3.8 版本中更改:
writexml()
方法现在保留用户指定的属性顺序。在 3.9 版本中更改: 添加了 standalone 参数。
- Node.toxml(encoding=None, standalone=None)¶
返回包含 DOM 节点表示的 XML 的字符串或字节字符串。
使用显式 encoding [1] 参数,结果是指定编码的字节字符串。如果没有 encoding 参数,结果是 Unicode 字符串,并且结果字符串中的 XML 声明不指定编码。将此字符串编码为 UTF-8 以外的编码可能不正确,因为 UTF-8 是 XML 的默认编码。
standalone 参数的行为与
writexml()
中相应的参数完全相同。在 3.8 版本中更改:
toxml()
方法现在保留用户指定的属性顺序。在 3.9 版本中更改: 添加了 standalone 参数。
- Node.toprettyxml(indent='\t', newl='\n', encoding=None, standalone=None)¶
返回文档的漂亮打印版本。indent 指定缩进字符串,默认为制表符;newl 指定每行末尾发出的字符串,默认为
\n
。encoding 参数的行为与
toxml()
的相应参数相同。standalone 参数的行为与
writexml()
中相应的参数完全相同。在 3.8 版本中更改:
toprettyxml()
方法现在保留用户指定的属性顺序。在 3.9 版本中更改: 添加了 standalone 参数。
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(f"<title>{getText(title.childNodes)}</title>")
def handleSlideTitle(title):
print(f"<h2>{getText(title.childNodes)}</h2>")
def handlePoints(points):
print("<ul>")
for point in points:
handlePoint(point)
print("</ul>")
def handlePoint(point):
print(f"<li>{getText(point.childNodes)}</li>")
def handleToc(slides):
for slide in slides:
title = slide.getElementsByTagName("title")[0]
print(f"<p>{getText(title.childNodes)}</p>")
handleSlideshow(dom)
minidom 和 DOM 标准¶
xml.dom.minidom
模块本质上是与 DOM 1.0 兼容的 DOM,并带有一些 DOM 2 功能(主要是命名空间功能)。
在 Python 中使用 DOM 接口非常简单。以下映射规则适用
通过实例对象访问接口。应用程序不应自行实例化类;它们应使用
Document
对象上可用的创建者函数。派生接口支持基本接口的所有操作(和属性),以及任何新操作。操作用作方法。由于 DOM 只使用
in
参数,因此参数按正常顺序(从左到右)传递。没有可选参数。void
操作返回None
。IDL 属性映射到实例属性。为了与 OMG IDL Python 语言映射兼容,属性
foo
也可以通过访问器方法_get_foo()
和_set_foo()
访问。readonly
属性不得更改;这在运行时不强制执行。类型
short int
、unsigned int
、unsigned long long
和boolean
都映射到 Python 整数对象。类型
DOMString
映射到 Python 字符串。xml.dom.minidom
支持字节或字符串,但通常会生成字符串。类型为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 的内置列表类型实现。这些对象提供 DOM 规范中定义的接口,但在早期版本的 Python 中,它们不支持官方 API。然而,它们比 W3C 推荐标准中定义的接口更“Pythonic”。
以下接口在 xml.dom.minidom
中没有实现
DOMTimeStamp
EntityReference
其中大部分反映了 XML 文档中对大多数 DOM 用户没有普遍实用价值的信息。
脚注