xml.dom.minidom– 最小的DOM实现

源代码: Lib / xml / dom / minidom.py


xml.dom.minidom是Document ObjectModel接口的最小实现,其API类似于其他语言。它旨在比完整的DOM更简单,也更小。不熟悉DOM的用户应该考虑使用xml.etree.ElementTree代替他们进行XML处理的模块.

警告

xml.dom.minidom模块不能安全地防止恶意构造的数据。如果您需要解析不受信任的orunauthenticated数据,请参阅XML漏洞.

DOM应用程序通常首先将一些XML解析为DOM。用xml.dom.minidom,这是通过解析函数完成的:

from xml.dom.minidom import parse, parseStringdom1 = parse("c:\\temp\\mydata.xml")  # parse an XML file by namedatasource = open("c:\\temp\\mydata.xml")dom2 = parse(datasource)  # parse an open filedom3 = parseString("<myxml>Some data<empty/> some more data</myxml>")

parse()函数可以采用文件名或打开的文件对象.

xml.dom.minidom.parse(filename_or_file, parser=None, bufsize=None)

从给定的输入返回Documentfilename_or_file可以是文件名,也可以是文件类对象。parser如果给定,则必须是SAX2parser对象。此函数将更改解析器的文档处理程序并激活名称空间支持;其他解析器配置(如设置实体解析器)必须事先完成.

如果你有一个字符串中的XML,你可以使用parseString() functioninstead:

xml.dom.minidom.parseStringstring, parser=None

返回Document代表string。这个方法创建一个io.StringIO字符串的对象并将其传递给parse().

两个函数都返回一个Document对象,表示文档的内容.

parse()parseString()函数do是将XMLparser与“DOM构建器”连接起来,该构建器可以接受来自任何SAX解析器的解析事件并将它们转换为DOM树。函数的名称可能会产生误导,但在学习接口时很容易掌握。在这些函数返回之前,文档的解析将完成;只是这些功能本身不提供解析器实现.

你也可以创建一个Document通过在“DOMImplementation”对象上调用方法。您可以通过调用getDOMImplementation()包中的xml.dom函数或xml.dom.minidom模块来获取此对象。一旦你有了Document,就可以向它添加子节点来填充DOM:

from xml.dom.minidom import getDOMImplementationimpl = getDOMImplementation()newdoc = impl.createDocument(None, "some_tag", None)top_element = newdoc.documentElementtext = 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.

DOM对象

用于Python的DOM API的定义是作为xml.dom模块文档的一部分给出的。本节列出了API与xml.dom.minidom.

打破DOM中的内部引用,以便在没有循环GC的情况下对Python进行垃圾回收。即使循环GC可用,使用这可以使更多的内存更快可用,所以在不再需要DOMobjects时立即调用它是很好的做法。这只需要在上调用Document对象,但可以在子节点上调用以丢弃该节点的子节点.

您可以通过使用with语句来避免显式调用此方法。以下代码将自动取消链接dom退出with块时:

with xml.dom.minidom.parse(datasource) as dom:    ... # Work with dom.
Node.writexmlwriter, indent=””, addindent=””, newl=””

XML写入writer对象。作者应该有一个write()methodwhich匹配文件对象接口的方法。indent参数是当前节点的压缩。addindent参数是用于当前子节点的incrementalIdentation。newl参数指定用于终止换行的字符串.

对于Document节点,可以使用附加的关键字参数encoding来指定编码字段XML header.

Node.toxml (encoding=None)

返回包含DOM节点所代表的XML的字符串或字节字符串.

有明确的encoding [1]参数,结果是指定编码中的字节串。没有encoding参数,结果是一个Unicode字符串,结果字符串中的XML声明没有指定编码。使用UTF-8以外的编码对此字符串进行编码可能不正确,因为UTF-8是XML的默认编码.

Node.toprettyxml(indent=”\t”, newl=”\n”, encoding=None)

返回一个漂亮的打印该文件的版本。indent指定压缩字符串并默认为制表符;newl指定每行末尾的stringemitted并默认为\n.

encoding参数的行为类似于toxml().

DOM的对应参数示例

这个示例程序是一个简单程序的一个相当现实的例子。在这个特例中,我们没有太多利用DOM的灵活性

import xml.dom.minidomdocument = """\<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)

minidomDOM标准

xml.dom.minidom模块本质上是一个与DOM 1.0兼容的DOM有一些DOM 2功能(主要是命名空间功能).

在Python中使用DOM接口是直截了当的。以下映射规则适用:

  • 通过实例对象访问接口。应用程序不应该自己实例化类;他们应该使用Document对象上的创建函数。派生接口支持来自基接口的缓和(和属性),以及任何新操作.
  • 操作用作方法。由于DOM只使用in参数,参数按正常顺序(从左到右)传递。没有可选参数。void操作返回None.
  • IDL属性映射到实例属性。为了兼容Python的OMG IDLlanguage映射,也可以通过访问方法访问foo属性_get_foo()_set_foo(). readonly属性不得更改;这不是在运行时强制执行的.
  • 类型short int, unsigned int, unsigned long long,和boolean全部映射到Python整数对象.
  • 类型DOMString映射到Python字符串。xml.dom.minidom支持字节或字符串,但通常会产生字符串。类型为DOMString的值也可能是None允许IDL null值由来自W3C的DOM规范
  • const声明映射到各自范围内的变量(例如xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE);它们不能被改变.
  • DOMException目前在xml.dom.minidom中不支持。相反,xml.dom.minidom使用标准的Python异常,例如TypeErrorAttributeError.
  • NodeList使用Python的内置列表类型实现对象。这些对象提供了DOM规范中定义的接口,但是在早期版本的Python中,它们不支持官方API。然而,它们比W3Crecommendations中定义的接口更加“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-EncodingDecland https://www.iana.org/assignments/character-sets/character-sets.xhtml.