Python - 浏览目录中的所有 xml 文件,获取一个元素及其子元素并将它们放置在另一个 xml 文件中的正确位置
Posted
技术标签:
【中文标题】Python - 浏览目录中的所有 xml 文件,获取一个元素及其子元素并将它们放置在另一个 xml 文件中的正确位置【英文标题】:Python - Go through all xml files in directory, take one element with it's sub-elements and place them at correct spot in another xml file 【发布时间】:2021-11-16 18:23:58 【问题描述】:我在这里遇到一种情况,我必须遍历一个目录中的所有 xml 文件:
Get.xml
Set.xml
Try.xml
etc..
它们每个都有相似的结构但不一样,并且包含这样的元素:
<example atrib1='' atrib2= ''...>
<summary atrib1='' atrib2= ''...>
<properties>
</properties>
</summary>
<Elem>
<element1>
<element2>
<subelement2>
........
</subelement2>
<element2>
<element1>
</Elem>
</example>
但是我还有其他的,我们称之为 Main.xml,其中包含 Get、Set、Try 作为其元素的名称:
<example atrib1='' atrib2= ''...>
<summary atrib1='' atrib2= ''...>
<properties>
</properties>
</summary>
<Test name="Get">
</Test>
<Test name="Set">
</Test>
<Test name="Try">
</Test>
</example>
现在我需要如前所述遍历所有 XML 并获取元素及其子元素,并将其放在 Main.xml 中与当前 XML 名称匹配的确切位置,因此 final 应该是:
Main.xml
<example atrib1='' atrib2= ''...>
<summary atrib1='' atrib2= ''...>
<properties>
</properties>
</summary>
<Test name="Get">
<Elem>
<element1>
<element2>
<subelement2>
........
</subelement2>
<element2>
<element1>
</Elem>
</Test>
<Test name="Set">
<Elem>
<element1>
<element2>
<subelement2>
........
</subelement2>
<element2>
<element1>
</Elem>
</Test>
<Test name="Try">
<Elem>
<element1>
<element2>
<subelement2>
........
</subelement2>
<element2>
<element1>
</Elem>
</Test>
</example>
目前我有这两个函数正在替换不同 xml 文件中的两个相同元素,但很难修复它,因此我可以将整个元素复制到另一个文件的确切位置:
def find_child(node, with_name):
"""Recursively find node with given name"""
for element in list(node):
if element.tag == 'Elem':
return element
elif list(element):
sub_result = find_child(element, 'Elem')
if sub_result is not None:
return sub_result
return None
def replace_node(from_tree, to_tree, node_name):
"""
Replace node with given node_name in to_tree with
the same-named node from the from_tree
"""
# Find nodes of given name in each tree
from_node = find_child(from_tree.getroot(), 'Elem')
to_node = find_child(to_tree.getroot(), 'Test')
# Find where to substitute the from_node into the to_tree
to_parent, to_index = get_node_parent_info(to_tree, to_node)
# Replace to_node with from_node
to_parent.remove(to_node)
to_parent.insert(to_index, from_node)
def get_node_parent_info(tree, node):
"""
Return tuple of (parent, index) where:
parent = node's parent within tree
index = index of node under parent
"""
parent_map = c:p for p in tree.iter() for c in p
parent = parent_map[node]
return parent, list(parent).index(node)
for filename in files:
from_tree = ET.ElementTree(filename)
to_tree = ET.ElementTree(file='Main.xml')
replace_node(from_tree, to_tree, 'Elem')
ET.dump(to_tree)
to_tree.write('Main.xml')
我知道这行不通,因为我们没有两个相同的元素可以替换,我需要更好的解决方案,请协助!
我也尝试过类似的方法,只是简单地复制整个元素,但没有成功:
source_tree = ET.parse('Get.xml')
source_root = source_tree.getroot()
dest_tree = ET.parse('Main.xml')
dest_root = dest_tree.getroot()
for element in source_root:
if element.tag == 'Elem':
for delement in dest_root.iter('Test'):
name = delement.get('name')
if name == 'Get':
delement.append(element)
dest_tree.write('Main.xml', encoding='utf-8', xml_declaration=True)
我希望这里必须做什么很清楚.. 如果您对如何做到这一点有任何想法,请告诉我! 谢谢!
【问题讨论】:
【参考方案1】:我不确定这是否是您想要的,但它会在正确的 Test 元素下插入所有 Elem 元素。
import xml.etree.ElementTree as ET
main_tree = ET.parse('Main.xml')
for test_elem in main_tree.findall('Test'):
tree = ET.parse(f"test_elem.get('name').xml")
for elem in tree.findall("Elem"):
test_elem.append(elem)
with open('newmain.xml', 'wb') as f:
main_tree.write(f)
【讨论】:
【参考方案2】:所以我设法写了这个并且它有效,唯一的问题是它没有将 xml 打印为“漂亮的打印”:
files = os.listdir(#location)
for xml in files:
if xml.endswith('.xml'):
source_tree = ET.parse(xml)
source_root = source_tree.getroot()
dest_tree = ET.parse('Main.xml')
dest_root = dest_tree.getroot()
for element in source_root:
if element.tag == 'Elem':
to_copy = element
for delement in dest_root.iter('Test'):
name = delement.get('name')
if name+'.xml' == xml:
destination_root = delement
destination_root.append(to_copy)
dest_tree.write('Main.xml', encoding='utf-8', xml_declaration=True)
【讨论】:
在 Python 3.9 中,有一个内置的indent
函数用于使用 ElementTree 进行漂亮打印:docs.python.org/3/library/…。另请参阅***.com/q/749796/407651。以上是关于Python - 浏览目录中的所有 xml 文件,获取一个元素及其子元素并将它们放置在另一个 xml 文件中的正确位置的主要内容,如果未能解决你的问题,请参考以下文章
如何在Python中通过SFTP连接后列出目录中的所有文件夹和文件
如何在Python中通过SFTP连接后列出目录中的所有文件夹和文件
Python zipfile 库 - 从一个目录创建一个仅包含 .pdf 和 .xml 文件的 zip