来自 minidom getElementsByTagName 的元素顺序

Order of elements from minidom getElementsByTagName

从 Mindom 返回的元素的顺序是否 getElementsByTagName 与文档中相同层次结构/级别的元素的顺序相同?

    images = svg_doc.getElementsByTagName('image') 
    image_siblings = []
    for img in images:
        if img.parentNode.getAttribute('layertype') == 'transfer':
            if img.nextSibling is not None:
                if img.nextSibling.nodeName == 'image':
                    image_siblings.append(img.nextSibling)
                elif img.nextSibling.nextSibling is not None and img.nextSibling.nextSibling.nodeName == 'image':
                    image_siblings.append(img.nextSibling.nextSibling)

我需要知道 image_siblings 是否会以相同的顺序包含图像,它们以相同的层次结构放置在文档中。

我为 JavaScript 找到了类似的 question,但我不确定 Python(版本 3.5.2)Minidom getElementsByTagName 是否也是如此。

根据代码(在Python 2.7),getElementsByName方法依赖于_get_elements_by_tagName_helper函数,代码为:

def _get_elements_by_tagName_helper(parent, name, rc):
    for node in parent.childNodes:
        if node.nodeType == Node.ELEMENT_NODE and \
            (name == "*" or node.tagName == name):
            rc.append(node)
        _get_elements_by_tagName_helper(node, name, rc)
    return rc

这意味着 getElementByName 中的顺序与 childNodes 中的顺序相同。

但只有当 tagName 只出现在同一层级时才成立。注意在同一个函数中递归调用 _get_elements_by_tagName_helper,这意味着具有相同 tagName 且位于树中更深处的元素将与更高级别的元素交错。

如果 document 是指 XML 文本文件或字符串,那么问题将转移到解析器在创建元素时是否遵守顺序在 DOM。 如果您使用 xml.dom.minidom 中的 parse 函数,它会依赖 pyexpat 库,后者又会使用 expat C 库。

所以,简短的回答是:

If you have the tagName only present in the same level of hierarchy in the XML DOM, then the order is respected. If you have the same tagName in other nodes deeper in the tree, those elements will be interleaved with the ones of higher level. The respected order is the order of the elements in the minidom document object, which order depends on the parser.

看这个例子:

>>> import StringIO
>>> from xml.dom.minidom import parseString
>>> s = '''<head>
...   <tagName myatt="1"/>
...   <tagName myatt="2"/>
...   <tagName myatt="3"/>
...   <otherTag>
...     <otherDeeperTag>
...       <tagName myatt="3.1"/>
...       <tagName myatt="3.2"/>
...       <tagName myatt="3.3"/>
...     </otherDeeperTag>
...   </otherTag> 
...   <tagName myatt="4"/>
...   <tagName myatt="5"/>
... </head>'''
>>> doc = parseString(s)
>>> for e in doc.getElementsByTagName('tagName'):
...     print e.getAttribute('myatt')
... 
1
2
3
3.1
3.2
3.3
4
5

解析器似乎遵循 xml 字符串的排序结构(大多数解析器都遵循该顺序,因为它更容易遵守)但我找不到任何文档来证实它。我的意思是,这可能是(奇怪的)情况,解析器根据文档的大小,从使用列表移动到散列 table 来存储元素,这可能会破坏顺序。考虑到 XML 标准没有指定元素的顺序,因此不遵守顺序的解析器也会被投诉。