代码之家  ›  专栏  ›  技术社区  ›  JokerMartini

按标签在每个元素后插入XML节点

  •  0
  • JokerMartini  · 技术社区  · 2 年前

    我有以下xml,我想插入一个 <separatorItem/> 之后每 </subMenu> 这有一个 <scriptItem/> 之后。

    或者换句话说,你可以重新措辞,因为我想插入一个 <分隔符项目/> 在xml层次结构的每个级别,在最后一个级别之后 <subMenu> 它在同一级别内包含更多元素。

    <?xml version="1.0" encoding="UTF-8"?>
    <mainMenu>
        <menuBar>
            <subMenu>
                <label>Main</label>
                <subMenu>
                    <label>Sub Menu</label>
                    <subMenu>
                        <label>Sub-Sub Menu</label>
                        <scriptItem>
                            <label>Email</label>
                        </scriptItem>
                    </subMenu>
                    <scriptItem>
                        <label>Manager</label>
                    </scriptItem>
                </subMenu>
                <subMenu>
                    <label>Dev</label>
                    <scriptItem>
                        <label>Dialog</label>
                    </scriptItem>
                </subMenu>
                <scriptItem>
                    <label>Sample</label>
                </scriptItem>
                <scriptItem>
                    <label>Home</label>
                </scriptItem>
                <scriptItem>
                    <label>Browser</label>
                </scriptItem>
                <scriptItem>
                    <label>Check</label>
                </scriptItem>
                <scriptItem>
                    <label>Open</label>
                </scriptItem>
                <scriptItem>
                    <label>Close</label>
                </scriptItem>
            </subMenu>
        </menuBar>
    </mainMenu>
    

    起始代码

    import os
    import re
    import sys
    import logging
    import xml.dom.minidom
    import xml.etree.ElementTree as ET
    
    
    fp = os.path.abspath('elementTree.xml')
    tree = ET.parse(fp)
    root = tree.getroot()
    
    # insert separator after every subMenu that's followed by a scriptItem
    # parent = None
    # for el in root.iter():
        # parent = root # find correct subMenu to place sep after
        # sep = ET.SubElement(parent, 'separatorItem')
    sep = ET.Element('separatorItem')
    root.insert(1, sep)
    
    
    xmlstr = ET.tostring(root, encoding='UTF-8', method="xml")
    xmlObj = xml.dom.minidom.parseString(xmlstr)
    xmlstr = xmlObj.toprettyxml(encoding='UTF-8')
    
    menuFilepath = os.path.abspath('updated.xml')
    with open(menuFilepath, 'wb') as output:
        output.write(xmlstr)
    

    最终目标看起来像这样。。。

    <?xml version="1.0" encoding="UTF-8"?>
    <mainMenu>
        <menuBar>
            <subMenu>
                <label>Main</label>
                <subMenu>
                    <label>Sub Menu</label>
                    <subMenu>
                        <label>Sub-Sub Menu</label>
                        <scriptItem>
                            <label>Email</label>
                        </scriptItem>
                    </subMenu>
                    <separatorItem/> <!-- INSERTED !-->
                    <scriptItem>
                        <label>Manager</label>
                    </scriptItem>
                </subMenu>
                <subMenu>
                    <label>Dev</label>
                    <scriptItem>
                        <label>Dialog</label>
                    </scriptItem>
                </subMenu>
                <separatorItem/> <!-- INSERTED !-->
                <scriptItem>
                    <label>Sample</label>
                </scriptItem>
                <scriptItem>
                    <label>Home</label>
                </scriptItem>
                <scriptItem>
                    <label>Browser</label>
                </scriptItem>
                <scriptItem>
                    <label>Check</label>
                </scriptItem>
                <scriptItem>
                    <label>Open</label>
                </scriptItem>
                <scriptItem>
                    <label>Close</label>
                </scriptItem>
            </subMenu>
        </menuBar>
    </mainMenu>
    
    
    0 回复  |  直到 2 年前
        1
  •  0
  •   Jack Fleeting    2 年前

    我会使用lxml,因为它对xpath的支持更好:

    from lxml import etree as etree
    menus = """[your xml above]"""
    
    doc = etree.fromstring(menus.encode())
    targets = doc.xpath('//subMenu[not(.//subMenu)][./scriptItem]')
    for target in targets:
        sep = etree.fromstring("""<separatorItem/>""".encode())
        target.addnext(sep)       
    
    print(etree.tostring(doc).decode())
    

    输出应该是你想要的。