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

我在这里有一种情况,我必须浏览一个目录中的所有 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,所以最后应该是:

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)

我希望很清楚这里必须做什么.. 如果您对如何做到这一点有任何想法,请告诉我! 谢谢!

我不确定这是否是您想要的,但它将所有 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)

所以我设法写了这个并且它有效,唯一的问题是它没有打印 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)