20.7. xml.dom.minidom
- 最小DOM实现¶
源代码: Lib / xml / dom / minidom.py
xml.dom.minidom
是文档对象模型接口的最小实现,其API类似于其他语言。它的目的是比完整的DOM更简单,也显着更小。尚未熟悉DOM的用户应考虑使用xml.etree.ElementTree
模块进行XML处理。
警告
xml.dom.minidom
模块对于恶意构造的数据不安全。如果需要解析不受信任或未经身份验证的数据,请参阅XML vulnerabilities。
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 may be either a file name, or a file-like object.解析器(如果给出)必须是SAX2解析器对象。此函数将更改解析器的文档处理程序并激活命名空间支持;其他解析器配置(如设置实体解析器)必须提前完成。
如果在字符串中有XML,可以使用parseString()
函数:
-
xml.dom.minidom.
parseString
(string, parser=None)¶ 返回表示字符串的
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的建议。
20.7.1. DOM Objects¶
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="")¶ 将XML写入writer对象。写入程序应该有一个与文件对象接口匹配的
write()
方法。缩进参数是当前节点的缩进。addindent参数是用于当前子节点的增量缩进。newl参数指定用于终止换行符的字符串。对于
Document
节点,可以使用附加的关键字参数encoding来指定XML标头的编码字段。
20.7.2. DOM Example¶
这个例子程序是一个简单程序的一个相当现实的例子。在这种特殊情况下,我们没有利用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)
20.7.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
属性不能更改;这不是在运行时强制。 - 类型
短 int
,无符号 int
unsigned long long
和boolean
- 类型
DOMString
映射到Python字符串。xml.dom.minidom
支持字节或字符串,但通常会产生字符串。类型DOMString
的值也可以是None
,其中允许具有来自W3C的DOM规范的IDLnull
值。 const
声明映射到它们各自范围内的变量。xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE
);它们不能改变。xml.dom.minidom
中目前不支持DOMException
。而是,xml.dom.minidom
使用标准Python异常,例如TypeError
和AttributeError
。NodeList
对象使用Python的内建列表类型实现。这些对象提供了在DOM规范中定义的接口,但是对于早期版本的Python,它们不支持官方API。然而,它们比W3C建议中定义的接口更加“Pythonic”。
以下接口在xml.dom.minidom
中没有实现:
DOMTimeStamp
DocumentType
DOMImplementation
CharacterData
CDATASection
Notation
Entity
EntityReference
DocumentFragment
大多数这些都反映在XML文档中的信息,这对大多数DOM用户来说不是通用的。
脚注
[1] | XML输出中包含的编码名称应符合相应的标准。例如,“UTF-8”有效,但“UTF8”在XML文档的声明中无效,即使Python接受它作为编码名称。请参阅https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl和https://www.iana.org/assignments/character- sets / character-sets.xhtml。 |