Skip to main content

20.6. xml.dom —文档对象模型API

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


文档对象模型或“DOM”是来自万维网联盟(W3C)的用于访问和修改XML文档的跨语言API。 DOM实现将XML文档呈现为树结构,或者允许客户端代码从头开始构建这样的结构。然后它通过一组提供众所周知的接口的对象来访问结构。

DOM对于随机访问应用非常有用。 SAX只允许一次查看文档的一个位。如果你正在查看一个SAX元素,你没有访问另一个。如果查看文本节点,则不能访问包含元素。当您编写SAX应用程序时,您需要在您自己的代码中的某处记录您的程序在文档中的位置。 SAX不会为你做。另外,如果你需要在XML文档中向前看,你只是运气不好。

一些应用程序在不能访问树的事件驱动模型中是不可能的。当然,你可以在SAX事件中自己构建一些树,但DOM允许你避免编写代码。 DOM是XML数据的标准树表示。

文档对象模型正在由W3C逐步定义,或者在术语中的“级别”。 API的Python映射基本上基于DOM Level 2推荐。

DOM应用程序通常首先将一些XML解析为DOM。这是如何实现的DOM级别1完全没有涵盖,级别2仅提供有限的改进:有一个 DOMImplementation 对象类,提供对 Document 创建方法的访问,但没有办法访问XML阅读器/解析器/文档构建器一种实现独立的方式。也没有定义良好的方法来访问这些方法,而没有现有的 Document 对象。在Python中,每个DOM实现都将提供一个函数 getDOMImplementation()。 DOM Level 3添加了一个加载/存储规范,它定义了一个读取器的接口,但这在Python标准库中还不可用。

一旦有了DOM文档对象,就可以通过其属性和方法访问XML文档的部分。这些属性在DOM规范中定义;这部分的参考手册描述了Python中对规范的解释。

W3C提供的规范定义了Java,ECMAScript和OMG IDL的DOM API。这里定义的Python映射在很大程度上基于规范的IDL版本,但不需要严格的遵从性(尽管实现可以自由地支持来自IDL的严格映射)。有关映射要求的详细讨论,请参见 一致性 部分。

参见

文档对象模型(DOM)2级规范

Python DOM API所基于的W3C建议。

文档对象模型(DOM)1级规范

W3C对 xml.dom.minidom 支持的DOM的建议。

Python语言映射规范

这指定从OMG IDL到Python的映射。

20.6.1. 模块内容

xml.dom 包含以下功能:

xml.dom.registerDOMImplementation(name, factory)

使用名称 name 注册 factory 函数。工厂函数应该返回一个实现 DOMImplementation 接口的对象。工厂函数可以每次返回相同的对象,或者对于每个调用返回一个对于特定实现(例如,如果该实现支持一些定制)适当的对象。

xml.dom.getDOMImplementation(name=None, features=())

返回一个合适的DOM实现。 name 是众所周知的,DOM实现的模块名称,或 None。如果不是 None,则导入相应的模块,如果导入成功,则返回 DOMImplementation 对象。如果没有给出名称,并且如果设置了环境变量 PYTHON_DOM,则此变量用于查找实现。

如果没有给出名称,这将检查可用的实现,以找到具有所需要的特征集。如果没有找到实施,提出 ImportError。功能列表必须是 (feature, version) 对的序列,它们传递到可用 DOMImplementation 对象上的 hasFeature() 方法。

还提供了一些方便常数:

xml.dom.EMPTY_NAMESPACE

用于指示没有命名空间与DOM中的节点相关联的值。这通常作为节点的 namespaceURI 找到,或者用作命名空间特定方法的 namespaceURI 参数。

xml.dom.XML_NAMESPACE

与保留前缀 xml 相关联的命名空间URI,由 XML中的命名空间 (第4节)定义。

xml.dom.XMLNS_NAMESPACE

命名空间声明的命名空间URI,由 文档对象模型(DOM)2级核心规范 定义(第1.1.8节)。

xml.dom.XHTML_NAMESPACE

XHTML 1.0:可扩展超文本标记语言 定义的XHTML命名空间的URI(第3.1.1节)。

此外,xml.dom 包含基本 Node 类和DOM异常类。此模块提供的 Node 类不实现DOM规范定义的任何方法或属性;具体的DOM实现必须提供那些。作为该模块一部分提供的 Node 类提供了用于具体 Node 对象上的 nodeType 属性的常量;它们位于类中,而不是位于模块级,以符合DOM规范。

20.6.2. DOM中的对象

DOM的定义文档是来自W3C的DOM规范。

注意,DOM属性也可以作为节点而不是简单的字符串来操作。但是,这是非常罕见的,因此这种用法还没有记录。

接口

部分

目的

DOMImplementation

DOMImplementation对象

底层实现的接口。

Node

节点对象

文档中大多数对象的基本接口。

NodeList

NodeList对象

节点序列的接口。

DocumentType

DocumentType对象

有关处理文档所需的声明的信息。

Document

文档对象

表示整个文档的对象。

Element

元素对象

文档层次结构中的元素节点。

Attr

Attr对象

元素节点上的属性值节点。

Comment

注释对象

表示源文档中的注释。

Text

文本和CDATASection对象

包含文档中文本内容的节点。

ProcessingInstruction

ProcessingInstruction对象

处理指令表示。

附加部分描述了为在Python中使用DOM定义的异常。

20.6.2.1. DOMImplementation对象

DOMImplementation 接口为应用程序提供了一种确定其所使用的DOM中的特定功能的可用性的方法。 DOM Level 2添加了使用 DOMImplementation 创建新的 DocumentDocumentType 对象的能力。

DOMImplementation.hasFeature(feature, version)

如果实现由字符串 featureversion 标识的功能,则返回true。

DOMImplementation.createDocument(namespaceUri, qualifiedName, doctype)

返回一个新的 Document 对象(DOM的根),使用具有给定 namespaceUriqualifiedName 的子 Element 对象。 doctype 必须是由 createDocumentType()None 创建的 DocumentType 对象。在Python DOM API中,前两个参数也可以是 None,以表示不要创建 Element 子节点。

DOMImplementation.createDocumentType(qualifiedName, publicId, systemId)

返回一个新的 DocumentType 对象,它封装给定的 qualifiedNamepublicIdsystemId 字符串,表示包含在XML文档类型声明中的信息。

20.6.2.2. 节点对象

XML文档的所有组件都是 Node 的子类。

Node.nodeType

表示节点类型的整数。类型的符号常数在 Node 对象上:ELEMENT_NODEATTRIBUTE_NODETEXT_NODECDATA_SECTION_NODEENTITY_NODEPROCESSING_INSTRUCTION_NODECOMMENT_NODEDOCUMENT_NODEDOCUMENT_TYPE_NODENOTATION_NODE。这是一个只读属性。

Node.parentNode

当前节点的父级,或文档节点的 None。该值始终为 Node 对象或 None。对于 Element 节点,这将是父元素,除了根元素,在这种情况下它将是 Document 对象。对于 Attr 节点,这总是 None。这是一个只读属性。

Node.attributes

属性对象的 NamedNodeMap。只有元素具有实际值;其他人为此属性提供 None。这是一个只读属性。

Node.previousSibling

紧接在此之前的节点具有相同的父节点。例如,具有结束标记的元素就在 self 元素的开始标记之前。当然,XML文档不仅仅是元素,所以前面的兄弟可以是文本,注释或其他东西。如果此节点是父级的第一个子级,则此属性将为 None。这是一个只读属性。

Node.nextSibling

紧随此后的节点具有相同的父节点。参见 previousSibling。如果这是父级的最后一个子级,则此属性将为 None。这是一个只读属性。

Node.childNodes

此节点中包含的节点的列表。这是一个只读属性。

Node.firstChild

节点的第一个子节点,如果有的话,或者 None。这是一个只读属性。

Node.lastChild

节点的最后一个子节点,如果有任何节点,或 None。这是一个只读属性。

Node.localName

tagName 的部分在冒号后面,如果有一个,否则整个 tagName。该值是一个字符串。

Node.prefix

冒号前面的 tagName 部分,如果有一个,否则空字符串。该值是一个字符串,或 None

Node.namespaceURI

与元素名称相关联的命名空间。这将是一个字符串或 None。这是一个只读属性。

Node.nodeName

这对于每个节点类型具有不同的含义;有关详细信息,请参阅DOM规范。您可以随时从其他属性获取此处获取的信息,例如元素的 tagName 属性或属性的 name 属性。对于所有节点类型,此属性的值将是字符串或 None。这是一个只读属性。

Node.nodeValue

这对于每个节点类型具有不同的含义;有关详细信息,请参阅DOM规范。情况类似于 nodeName。值为字符串或 None

Node.hasAttributes()

如果节点有任何属性,则返回true。

Node.hasChildNodes()

如果节点有任何子节点,则返回true。

Node.isSameNode(other)

如果 other 引用与此节点相同的节点,则返回true。这对于使用任何类型的代理体系结构的DOM实现(因为多个对象可以引用同一个节点)特别有用。

注解

这是基于一个仍然在“工作草案”阶段提出的DOM 3级API,但这个特定的接口显示无争议。 W3C中的更改不一定会影响Python DOM接口中的此方法(尽管也将支持任何新的W3C API)。

Node.appendChild(newChild)

在子节点列表的末尾向此节点添加一个新的子节点,返回 newChild。如果节点已经在树中,则首先将其删除。

Node.insertBefore(newChild, refChild)

在现有子节点之前插入新的子节点。必须是 refChild 是这个节点的子节点的情况;如果不是,则提高 ValueError。返回 newChild。如果 refChildNone,它将在子表的末尾插入 newChild

Node.removeChild(oldChild)

删除子节点。 oldChild 必须是此节点的子节点;如果不是,则提高 ValueError。成功返回 oldChild。如果 oldChild 不会被进一步使用,则应调用其 unlink() 方法。

Node.replaceChild(newChild, oldChild)

将现有节点替换为新节点。必须是 oldChild 是这个节点的子节点的情况;如果不是,则提高 ValueError

Node.normalize()

连接相邻的文本节点,以便所有文本段被存储为单个 Text 实例。这简化了从许多应用程序的DOM树处理文本。

Node.cloneNode(deep)

克隆此节点。设置 deep 意味着也克隆所有子节点。这将返回克隆。

20.6.2.3. NodeList对象

NodeList 表示节点序列。这些对象在DOM Core推荐中以两种方式使用:Element 对象提供一个作为其子节点的列表,NodegetElementsByTagName()getElementsByTagNameNS() 方法返回具有该接口的对象以表示查询结果。

DOM级别2建议为这些对象定义了一个方法和一个属性:

NodeList.item(i)

从序列中返回 i 项,如果有一个,或 None。索引 i 不允许小于零或大于或等于序列的长度。

NodeList.length

序列中的节点数。

此外,Python DOM接口需要提供一些额外的支持,以允许 NodeList 对象用作Python序列。所有 NodeList 实施必须包括对 __len__()__getitem__() 的支持;这允许在 for 语句中对 NodeList 进行迭代,并对 len() 内置函数提供正确的支持。

如果DOM实现支持文档的修改,则 NodeList 实现还必须支持 __setitem__()__delitem__() 方法。

20.6.2.4. DocumentType对象

关于文档声明的符号和实体的信息(包括外部子集,如果解析器使用它并且可以提供信息)可从 DocumentType 对象获得。文档的 DocumentType 可从 Document 对象的 doctype 属性获取;如果文档没有 DOCTYPE 声明,则文档的 doctype 属性将设置为 None,而不是此接口的实例。

DocumentTypeNode 的一个专门化,并添加了以下属性:

DocumentType.publicId

文档类型定义的外部子集的公共标识符。这将是一个字符串或 None

DocumentType.systemId

文档类型定义的外部子集的系统标识符。这将是一个URI作为字符串,或 None

DocumentType.internalSubset

从文档提供完整内部子集的字符串。这不包括括起子集的括号。如果文档没有内部子集,则应为 None

DocumentType.name

DOCTYPE 声明中给出的根元素的名称(如果存在)。

DocumentType.entities

这是一个 NamedNodeMap 给出外部实体的定义。对于多次定义的实体名称,仅提供第一个定义(根据XML建议的要求,忽略其他定义)。如果信息不是由解析器提供,或者如果没有定义实体,这可能是 None

DocumentType.notations

这是一个 NamedNodeMap 给出符号的定义。对于多次定义的符号名称,仅提供第一个定义(根据XML建议的要求,忽略其他定义)。如果信息不是由解析器提供的,或者如果没有定义符号,这可能是 None

20.6.2.5. 文档对象

Document 表示整个XML文档,包括其组成元素,属性,处理指令,注释等。请记住,它从 Node 继承属性。

Document.documentElement

文档的唯一根元素。

Document.createElement(tagName)

创建并返回一个新的元素节点。创建文档时,元素不会插入到文档中。您需要使用其他方法(如 insertBefore()appendChild())显式插入它。

Document.createElementNS(namespaceURI, tagName)

创建并返回一个带有命名空间的新元素。 tagName 可以具有前缀。创建文档时,元素不会插入到文档中。您需要使用其他方法(如 insertBefore()appendChild())显式插入。

Document.createTextNode(data)

创建并返回包含作为参数传递的数据的文本节点。与其他创建方法一样,此方法不会将节点插入到树中。

Document.createComment(data)

创建并返回包含作为参数传递的数据的注释节点。与其他创建方法一样,此方法不会将节点插入到树中。

Document.createProcessingInstruction(target, data)

创建并返回一个包含作为参数传递的 targetdata 的处理指令节点。与其他创建方法一样,此方法不会将节点插入到树中。

Document.createAttribute(name)

创建并返回一个属性节点。此方法不将属性节点与任何特定元素相关联。您必须在适当的 Element 对象上使用 setAttributeNode() 才能使用新创建的属性实例。

Document.createAttributeNS(namespaceURI, qualifiedName)

创建并返回带有命名空间的属性节点。 tagName 可以具有前缀。此方法不将属性节点与任何特定元素相关联。必须在适当的 Element 对象上使用 setAttributeNode() 才能使用新创建的属性实例。

Document.getElementsByTagName(tagName)

搜索具有特定元素类型名称的所有后代(直接子项,子项的子项等)。

Document.getElementsByTagNameNS(namespaceURI, localName)

搜索具有特定命名空间URI和本地名称的所有后代(直接子项,子项的子项等)。 localname是前缀后的命名空间的一部分。

20.6.2.6. 元素对象

ElementNode 的子类,因此继承该类的所有属性。

Element.tagName

元素类型名称。在使用命名空间的文档中,它可能有冒号。该值是一个字符串。

Element.getElementsByTagName(tagName)

Document 类中的等效方法相同。

Element.getElementsByTagNameNS(namespaceURI, localName)

Document 类中的等效方法相同。

Element.hasAttribute(name)

如果元素具有由 name 命名的属性,则返回true。

Element.hasAttributeNS(namespaceURI, localName)

如果元素具有由 namespaceURIlocalName 命名的属性,则返回true。

Element.getAttribute(name)

将由 name 命名的属性的值作为字符串返回。如果不存在这样的属性,则返回一个空字符串,就像该属性没有值一样。

Element.getAttributeNode(attrname)

返回由 attrname 命名的属性的 Attr 节点。

Element.getAttributeNS(namespaceURI, localName)

将由 namespaceURIlocalName 命名的属性的值返回为字符串。如果不存在这样的属性,则返回一个空字符串,就像该属性没有值一样。

Element.getAttributeNodeNS(namespaceURI, localName)

给定 namespaceURIlocalName,返回属性值作为节点。

Element.removeAttribute(name)

按名称删除属性。如果没有匹配属性,则引发 NotFoundErr

Element.removeAttributeNode(oldAttr)

从属性列表中删除并返回 oldAttr (如果存在)。如果 oldAttr 不存在,则引发 NotFoundErr

Element.removeAttributeNS(namespaceURI, localName)

按名称删除属性。注意,它使用localName,而不是qname。如果没有匹配的属性,则不会引发异常。

Element.setAttribute(name, value)

从字符串中设置属性值。

Element.setAttributeNode(newAttr)

向元素添加新的属性节点,如果 name 属性匹配,则替换现有属性。如果发生替换,将返回旧的属性节点。如果 newAttr 已经在使用,则 InuseAttributeErr 将被引发。

Element.setAttributeNodeNS(newAttr)

向元素添加新的属性节点,如果 namespaceURIlocalName 属性匹配,则替换现有属性。如果发生替换,将返回旧的属性节点。如果 newAttr 已经在使用,InuseAttributeErr 将被提出。

Element.setAttributeNS(namespaceURI, qname, value)

从字符串设置属性值,给定 namespaceURIqname。注意,qname是整个属性名称。这与上面不同。

20.6.2.7. Attr对象

AttrNode 继承,因此继承其所有属性。

Attr.name

属性名称。在使用命名空间的文档中,可以包含冒号。

Attr.localName

冒号之后的名称部分,如果有一个,否则整个名称。这是一个只读属性。

Attr.prefix

冒号前面的名称部分,如果有一个,否则空字符串。

Attr.value

属性的文本值。这是 nodeValue 属性的同义词。

20.6.2.8. NamedNodeMap对象

NamedNodeMap 确实 not 继承自 Node

NamedNodeMap.length

属性列表的长度。

NamedNodeMap.item(index)

返回具有特定索引的属性。获取属性的顺序是任意的,但对于DOM的生命是一致的。每个项目是一个属性节点。使用 value 属性获取其值。

还有实验方法给这个类更多的映射行为。您可以使用它们,也可以在 Element 对象上使用标准化的 getAttribute*() 系列方法。

20.6.2.9. 注释对象

Comment 表示XML文档中的注释。它是 Node 的子类,但不能有子节点。

Comment.data

注释的内容为字符串。该属性包含前导 <!- - 和尾部 - -> 之间的所有字符,但不包括它们。

20.6.2.10. 文本和CDATASection对象

Text 接口表示XML文档中的文本。如果解析器和DOM实现支持DOM的XML扩展,则包含在CDATA标记部分中的文本部分存储在 CDATASection 对象中。这两个接口是相同的,但为 nodeType 属性提供不同的值。

这些接口扩展了 Node 接口。他们不能有子节点。

Text.data

文本节点的内容作为字符串。

注解

CDATASection 节点的使用不表示节点表示完整的CDATA标记部分,只是节点的内容是CDATA部分的一部分。单个CDATA段可以由文档树中的多于一个节点表示。没有办法确定两个相邻的 CDATASection 节点是否代表不同的CDATA标记部分。

20.6.2.11. ProcessingInstruction对象

表示XML文档中的处理指令;这继承自 Node 接口,并且不能有子节点。

ProcessingInstruction.target

直到第一个空格字符的处理指令的内容。这是一个只读属性。

ProcessingInstruction.data

第一个空格字符后的处理指令的内容。

20.6.2.12. 例外

DOM级别2建议定义了单个异常,DOMException 和允许应用程序确定发生什么类型的错误的多个常量。 DOMException 实例携带 code 属性,为特定异常提供适当的值。

Python DOM接口提供常量,但也扩展了一组异常,使得DOM定义的每个异常代码都存在特定的异常。实现必须提出适当的特定异常,每个异常都携带 code 属性的适当值。

exception xml.dom.DOMException

基本异常类用于所有特定的DOM异常。此异常类不能直接实例化。

exception xml.dom.DomstringSizeErr

在指定范围的文本不适合字符串时引发。这不知道在Python DOM实现中使用,但可以从不是用Python编写的DOM实现接收。

exception xml.dom.HierarchyRequestErr

在尝试插入不允许节点类型的节点时引发。

exception xml.dom.IndexSizeErr

在方法的索引或大小参数为负值或超出允许值时引发。

exception xml.dom.InuseAttributeErr

在尝试插入已在文档中其他位置存在的 Attr 节点时引发。

exception xml.dom.InvalidAccessErr

在底层对象不支持参数或操作时触发。

exception xml.dom.InvalidCharacterErr

当字符串参数包含在XML 1.0建议中使用的上下文中不允许的字符时,会引发此异常。例如,尝试创建具有元素类型名称中的空格的 Element 节点将导致引发此错误。

exception xml.dom.InvalidModificationErr

在尝试修改节点类型时引发。

exception xml.dom.InvalidStateErr

在尝试使用未定义或不再可用的对象时引发。

exception xml.dom.NamespaceErr

如果试图以对 XML中的命名空间 建议不允许的方式更改任何对象,则会引发此异常。

exception xml.dom.NotFoundErr

在引用的上下文中不存在节点时的异常。例如,如果传入的节点不存在于映射中,NamedNodeMap.removeNamedItem() 将引发此异常。

exception xml.dom.NotSupportedErr

在实现不支持所请求类型的对象或操作时引发。

exception xml.dom.NoDataAllowedErr

如果为不支持数据的节点指定了数据,则会引发此错误。

exception xml.dom.NoModificationAllowedErr

在尝试修改不允许修改的对象(例如只读节点)时引发。

exception xml.dom.SyntaxErr

在指定无效或非法字符串时引发。

exception xml.dom.WrongDocumentErr

在节点插入到与当前所属的文档不同的文档中时引发,实现不支持将节点从一个文档迁移到另一个文档。

DOM建议中定义的异常代码根据此表映射到上述异常:

不变

例外

DOMSTRING_SIZE_ERR

DomstringSizeErr

HIERARCHY_REQUEST_ERR

HierarchyRequestErr

INDEX_SIZE_ERR

IndexSizeErr

INUSE_ATTRIBUTE_ERR

InuseAttributeErr

INVALID_ACCESS_ERR

InvalidAccessErr

INVALID_CHARACTER_ERR

InvalidCharacterErr

INVALID_MODIFICATION_ERR

InvalidModificationErr

INVALID_STATE_ERR

InvalidStateErr

NAMESPACE_ERR

NamespaceErr

NOT_FOUND_ERR

NotFoundErr

NOT_SUPPORTED_ERR

NotSupportedErr

NO_DATA_ALLOWED_ERR

NoDataAllowedErr

NO_MODIFICATION_ALLOWED_ERR

NoModificationAllowedErr

SYNTAX_ERR

SyntaxErr

WRONG_DOCUMENT_ERR

WrongDocumentErr

20.6.3. 一致性

本节描述了Python DOM API,W3C DOM建议和Python的OMG IDL映射之间的一致性要求和关系。

20.6.3.1. 类型映射

DOM规范中使用的IDL类型根据下表映射到Python类型。

IDL类型

Python类型

boolean

boolint

int

int

long int

int

unsigned int

int

DOMString

strbytes

null

None

20.6.3.2. 访问器方法

从OMG IDL到Python的映射以Java映射的方式定义了IDL attribute 声明的访问器函数。映射IDL声明

readonly attribute string someValue;
         attribute string anotherValue;

产生三个访问器函数:someValue 的“get”方法(_get_someValue()),以及 anotherValue_get_anotherValue()_set_anotherValue())的“get”和“set”方法。特别地,映射不要求IDL属性作为正常的Python属性可访问:object.someValue 是工作所需的 not,并且可以提高 AttributeError

但是,Python DOM API,does 要求正常的属性访问工作。这意味着由Python IDL编译器生成的典型代理不太可能工作,如果通过CORBA访问DOM对象,则客户端可能需要包装器对象。虽然这需要一些额外的考虑对CORBA DOM客户端,有经验使用DOM的CORBA从Python的实施者不认为这是一个问题。被声明为 readonly 的属性不能限制所有DOM实现中的写访问。

在Python DOM API中,不需要访问器函数。如果提供,它们应该采用由Python IDL映射定义的形式,但是这些方法被认为不必要,因为属性可以直接从Python访问。不应为 readonly 属性提供“设置”访问器。

IDL定义不完全体现W3C DOM API的要求,例如某些对象的概念,例如 getElementsByTagName() 的返回值,是“活的”。 Python DOM API不需要实现来实施这些要求。