xml.dom.minidom
— 最小 DOM 实现¶
xml.dom.minidom
是文档对象模型接口的最小实现,其 API 与其他语言中的 API 类似。它的目标是比完整的 DOM 更简单,而且也小得多。不熟悉 DOM 的用户应考虑使用 xml.etree.ElementTree
模块进行 XML 处理。
警告
xml.dom.minidom
模块对于恶意构造的数据是不安全的。如果需要解析不受信任或未经验证的数据,请参阅 XML 漏洞。
DOM 应用程序通常从将一些 XML 解析到 DOM 开始。使用 xml.dom.minidom
,这是通过 parse 函数完成的
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
包或 xml.dom.minidom
模块中的 getDOMImplementation()
函数来获取此对象。拥有 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 级规范
W3C 针对
xml.dom.minidom
支持的 DOM 的建议。
DOM 对象¶
Python 的 DOM API 定义作为 xml.dom
模块文档的一部分给出。本节列出了 API 和 xml.dom.minidom
之间的差异。
- Node.unlink()¶
断开 DOM 中的内部引用,以便在没有循环 GC 的 Python 版本上进行垃圾回收。即使在可以使用循环 GC 时,使用此方法也可以更快地释放大量内存,因此在不再需要 DOM 对象时立即调用此方法是一种好习惯。这只需要在
Document
对象上调用,但可以在子节点上调用以丢弃该节点的子节点。您可以使用
with
语句来避免显式调用此方法。以下代码将在退出with
代码块时自动取消链接 domwith 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 兼容,也可以通过访问器方法
_get_foo()
和_set_foo()
访问属性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 用户来说不是通用的。
脚注