Ctrl
+
D
一键收藏

最小的DOM实现

xml.dom.minidom

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


xml.dom.minidom 是文档对象模型接口的最小实现,其API与其他语言类似。它的目的是要比完整的DOM简单,而且要小得多。不熟悉DOM的用户应该考虑使用 xml.etree.ElementTree 用于XML处理的模块。

警告

这个 xml.dom.minidom 模块对恶意构造的数据不安全。如果需要分析不可信或未经身份验证的数据,请参阅 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)

返回A Document 从给定的输入。 filename_or_file 可以是文件名,也可以是类似文件的对象。 语法分析器 如果给定,则必须是SAX2解析器对象。此函数将更改解析器的文档处理程序并激活命名空间支持;其他解析器配置(如设置实体解析器)必须提前完成。

如果字符串中有XML,则可以使用 parseString() 改为函数:

xml.dom.minidom.parseString(string, parser=None)

返回A Document 代表了 string . 此方法创建一个 io.StringIO 对象,并将其传递给 parse() .

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

什么? parse()parseString() 函数的作用是将XML解析器与“dom builder”连接起来,后者可以接受来自任何SAX解析器的解析事件,并将其转换为dom树。函数的名称可能有误导性,但在学习接口时很容易掌握。文档的解析将在这些函数返回之前完成;只是这些函数本身不提供解析器实现。

您还可以创建 Document 通过对“dom实现”对象调用方法。您可以通过调用 getDOMImplementation() 功能在 xml.dom 封装还是 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对象

python的dom api定义作为 xml.dom 模块文档。本节列出了API和 xml.dom.minidom .

中断dom中的内部引用,以便在不使用循环gc的Python版本上对其进行垃圾收集。即使循环GC可用,使用它也可以使大量内存更快地可用,因此在不再需要DOM对象时立即调用它是一种很好的实践。这只需要在 Document 对象,但可以在子节点上调用以丢弃该节点的子节点。

通过使用 with 语句。以下代码将自动取消链接 domwith 块已退出::

with xml.dom.minidom.parse(datasource) as dom:
    ... # Work with dom.
Node.writexml(writer, indent='', addindent='', newl='', encoding=None, standalone=None)

将XML写入编写器对象。编写器接收文本而不是字节作为输入,它应该有一个 write() 与文件对象接口匹配的方法。这个 缩进 参数是当前节点的缩进。这个 附录 参数是用于当前子节点的增量缩进。这个 newl 参数指定用于终止换行符的字符串。

对于 Document 节点,附加关键字参数 encoding 可用于指定XML头的编码字段。

愚蠢地,明确地指出 独立的 参数导致将独立文档声明添加到XML文档的序言中。如果该值设置为 Truestandalone="yes" 添加,否则设置为 "no" . 不声明参数将忽略文档中的声明。

在 3.8 版更改: 这个 writexml() 方法现在保留用户指定的属性顺序。

Node.toxml(encoding=None, standalone=None)

返回包含由DOM节点表示的XML的字符串或字节字符串。

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

这个 独立的 参数的行为与 writexml() .

在 3.8 版更改: 这个 toxml() 方法现在保留用户指定的属性顺序。

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

返回文档的精美打印版本。 缩进 指定缩进字符串并默认为制表符; newl 指定每行末尾发出的字符串,默认为 \n .

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

这个 独立的 参数的行为与 writexml() .

在 3.8 版更改: 这个 toprettyxml() 方法现在保留用户指定的属性顺序。

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)

minidom和dom标准

这个 xml.dom.minidom 模块本质上是一个与一些dom 2特性(主要是命名空间特性)兼容的dom 1.0。

在python中使用dom接口是直接的。以下映射规则适用:

  • 通过实例对象访问接口。应用程序不应该实例化类本身;它们应该使用 Document 对象。派生接口支持来自基本接口的所有操作(和属性),以及任何新操作。

  • 操作用作方法。因为DOM只使用 in 参数,参数按正常顺序传递(从左到右)。没有可选参数。 void 操作返回 None .

  • IDL属性映射到实例属性。为了与用于python的omg idl语言映射兼容,属性 foo 也可以通过访问器方法访问 _get_foo()_set_foo() . readonly 属性不能更改;这在运行时不强制执行。

  • 类型 short intunsigned intunsigned long longboolean 所有映射到python integer对象。

  • 类型 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。然而,它们比W3C建议中定义的接口更“ Python 式”。

以下接口在中没有实现 xml.dom.minidom

  • DOMTimeStamp

  • EntityReference

其中大部分反映了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。

Ctrl
+
D
一键收藏