目录
访问上一篇:Python与XML文件处理详解(2):使用xml.dom.minidom模块处理XML
第一部分:高级节点操作与遍历方法
除了基础的 getElementsByTagName
,minidom
提供了更多定位和操作节点的工具。
1.1 更精确的节点导航
在处理由工具生成的XML(如ARXML)时,其结构往往是可预测的。利用这一点,我们可以进行精确导航。
import xml.dom.minidom as minidom
dom = minidom.parse('books.xml')
root = dom.documentElement
# 假设我们知道第一个book元素下第一个元素是author
first_book = root.getElementsByTagName('book')[0]
first_child_of_book = first_book.firstChild
# 但firstChild可能是文本节点(换行符),我们需要找到第一个元素节点
first_element_child = first_book.firstChild
while first_element_child is not None and first_element_child.nodeType != first_element_child.ELEMENT_NODE:
first_element_child = first_element_child.nextSibling
print(f"第一个元素子节点的标签是: {first_element_child.tagName}") # 输出: author
# 编写一个通用函数来获取第一个元素子节点
def get_first_element_child(node):
child = node.firstChild
while child is not None:
if child.nodeType == child.ELEMENT_NODE:
return child
child = child.nextSibling
return None
author_node = get_first_element_child(first_book)
1.2 使用 cloneNode()
复制节点
这在需要复制一个复杂节点结构时非常有用,例如在ARXML中复制一个ECU配置模板。
# 深度复制第一个book元素及其所有子孙节点
book_clone = first_book.cloneNode(deep=True)
# 修改克隆体的ID,避免冲突
book_clone.setAttribute('id', 'bk103_clone')
# 将克隆体添加到文档中
root.appendChild(book_clone)
# 浅复制(deep=False)只复制元素本身,不复制其子节点。适用于创建空模板。
empty_book_template = first_book.cloneNode(deep=False)
empty_book_template.setAttribute('id', 'new_template')
# 此时 empty_book_template 没有 author, title 等子元素
1.3 节点插入、替换与高级管理
# 创建一个新的price元素
new_price = dom.createElement('price')
new_price.appendChild(dom.createTextNode('75.00'))
# --- 在特定位置插入 ---
# 在author节点之后插入new_price
# 首先需要找到参考节点(author)和父节点
ref_node = first_book.getElementsByTagName('author')[0]
first_book.insertBefore(new_price, ref_node.nextSibling) # 插入到author之后
# --- 替换节点 ---
old_price = first_book.getElementsByTagName('price')[1] # 假设有第二个price
first_book.replaceChild(new_price, old_price) # 用new_price替换old_price
# --- 检查节点关系 ---
# 判断一个节点是否包含另一个节点
contains = first_book.hasChildNodes() # True
is_contained = new_price.parentNode.isSameNode(first_book) # True
# 获取同级节点中的下一个元素节点(跳过文本节点)
def get_next_element_sibling(node):
sibling = node.nextSibling
while sibling is not None:
if sibling.nodeType == sibling.ELEMENT_NODE:
return sibling
sibling = sibling.nextSibling
return None
next_ele = get_next_element_sibling(ref_node) # 获取author后面的元素,可能是title
</