I'm getting an issue when removing and adding elements to a xml file via ElementTree and Tkinter GUI.

This is just a simplified part of a piece of code that's why my naming conventions may seem a little weird and I'm also fairly new to python (I'm in year 12), nevertheless:

The issue is when a box(subelement of room0) is added to the xml file after removing some other boxes it adds all the boxes that were previously removed from the xml file, instead of just one.

my goal is to:

  • add boxes to the xml file under the room 0 element when the add box button is pressed

  • remove the respective box to its minus button

  • then be able to add 1 box per time the add box button is pressed (instead all that were removed) after subtracting boxes

XML tree: (file called "summary.xml"

<data>
    <room0 />
</data>

Code:

import tkinter as tk
from tkinter import *
import xml.etree.ElementTree as ET

root = Tk()
#root dimentions
root.geometry("500x560")
root.title("Box & room organiser")
root.resizable(False,False)
root.configure(background = "#2a2828")
#xml
tree = ET.parse("summary.xml")
xmlroot = tree.getroot()

#function that indents and writes xml file when called
def write_xml(tree):
    ET.indent(tree, space = '\t', level = 0)
    tree.write('summary.xml')

#iterates through the root finding elements of xmlroot
for room0 in xmlroot:
    if room0.tag == 'room0':
        xml_room0 = room0

#counter variable for amount of boxes in xml file        
box_count = 0

def add_box():
    global box_count
    box_count = box_count + 1

    #if box count is 1 add box 1
    if box_count == 1:

        # adding room0's box 1 to the xml file
        for room0 in xmlroot.findall('room0'):
            box1=ET.Element('box1')
            room0.append(box1)

        #alternative way of adding-->
        # xml_room0_box1 = ET.SubElement(xml_room0, "box1")

        write_xml(tree)
        print('box1 added')

    elif box_count == 2:
        #adding room0's box 2 to the xml file
        for room0 in xmlroot.findall('room0'):
            box2=ET.Element('box2')
            room0.append(box2)
        # xml_room0_box2 = ET.SubElement(xml_room0, "box2")
        write_xml(tree)
        print('box2 added')

    elif box_count == 3:
        #adding room0's box 3 to the xml file
        for room0 in xmlroot.findall('room0'):
            box3=ET.Element('box3')
            room0.append(box3)
        # xml_room0_box3 = ET.SubElement(xml_room0, "box3")

        write_xml(tree)
        print('box3 added')

    elif box_count == 4:
        #adding room0's box 4 to the xml file
        for room0 in xmlroot.findall('room0'):
            box4=ET.Element('box4')
            room0.append(box4)
        # xml_room0_box4 = ET.SubElement(xml_room0, "box4")

        write_xml(tree)
        print('box4 added')

    elif box_count == 5:
        #adding room0's box 5 to the xml file
        for room0 in xmlroot.findall('room0'):
            box5=ET.Element('box5')
            room0.append(box5)
        # xml_room0_box5 = ET.SubElement(xml_room0, "box5")

        write_xml(tree)
        print('box5 added')

    elif box_count == 6:
        #adding room0's box 6 to the xml file
        for room0 in xmlroot.findall('room0'):
            box6=ET.Element('box6')
            room0.append(box6)
        # xml_room0_box6 = ET.SubElement(xml_room0, "box6")
        write_xml(tree)
        print('box6 added')

add_box_button = Button(root, text = "+", command = add_box)
add_box_button.pack()

        #alternative minus code using etree
        # from lxml import etree (add at top if using alternative)
        # for elem in parse_tree.findall('//box1'): #findall or xpath (no difference)
        #     parent = elem.getparent()
        #     parent.remove(elem)
        # print(etree.tostring(parse_tree))
        # parse_tree.write('summary.xml')
    
def minus_box1():
#removes box1 element from xml file
    global box_count
    box_count = box_count - 1

    tree =ET.parse('summary.xml')
    xml_root = tree.getroot()

    for room0 in xml_root:
        if room0.tag == 'room0':
            for box1 in room0:
                if box1.tag == 'box1':
                    room0.remove(box1)
    write_xml(tree)
    print('box1 minused')
    
def minus_box2():
    global box_count
    box_count = box_count - 1
    #removes box1 element from summary.xml
    tree=ET.parse('summary.xml')
    xmlroot = tree.getroot()

    for room0 in xmlroot:
        if room0.tag == 'room0':
            for box2 in room0:
                if box2.tag == 'box2':
                    room0.remove(box2)
    write_xml(tree)
    print('box2 minused')

def minus_box3():
    global box_count
    box_count = box_count - 1
    #removes box1 element from summary.xml
    tree=ET.parse('summary.xml')
    xmlroot = tree.getroot()

    for room0 in xmlroot:
        if room0.tag == 'room0':
            for box3 in room0:
                if box3.tag == 'box3':
                    room0.remove(box3)
    write_xml(tree)
    print('box3 minused')

def minus_box4():
    global box_count
    box_count = box_count - 1
    #removes box1 element from summary.xml
    tree=ET.parse('summary.xml')
    xmlroot = tree.getroot()

    for room0 in xmlroot:
        if room0.tag == 'room0':
            for box4 in room0:
                if box4.tag == 'box4':
                    room0.remove(box4)
    write_xml(tree)
    print('box4 minused')

def minus_box5():
    global box_count
    box_count = box_count - 1
    #removes box1 element from summary.xml
    tree=ET.parse('summary.xml')
    xmlroot = tree.getroot()

    for room0 in xmlroot:
        if room0.tag == 'room0':
            for box5 in room0:
                if box5.tag == 'box5':
                    room0.remove(box5)
    write_xml(tree)
    print('box5 minused')

def minus_box6():
    global box_count
    box_count = box_count - 1
    #removes box1 element from summary.xml
    tree=ET.parse('summary.xml')
    xmlroot = tree.getroot()

    for room0 in xmlroot:
        if room0.tag == 'room0':
            for box6 in room0:
                if box6.tag == 'box6':
                    room0.remove(box6)
    write_xml(tree)
    print('box6 minused')

#minus box buttons
room0_box1_minus_button = Button(root, text="-b1", bg = "#2b2828", command = minus_box1)
room0_box1_minus_button.pack()

room0_box2_minus_button = Button(root, text="-b2", bg = "#2b2828", command = minus_box2)
room0_box2_minus_button.pack()

room0_box3_minus_button = Button(root, text="-b3", bg = "#2b2828", command = minus_box3)
room0_box3_minus_button.pack()

room0_box4_minus_button = Button(root, text="-b4", bg = "#2b2828", command = minus_box4)
room0_box4_minus_button.pack()

room0_box5_minus_button = Button(root, text="-b5", bg = "#2b2828", command = minus_box5)
room0_box5_minus_button.pack()

room0_box6_minus_button = Button(root, text="-b6", bg = "#2b2828", command = minus_box6)
room0_box6_minus_button.pack()
root.mainloop()

推荐答案

The first thing I'd do is get rid of all of those if statements, weather they're causing the problem or not, they aren't very efficient.

I'd say replace them with a function that will get all of the 'boxes' from a 'room' in form of a list. That way you can just call len() (which gets the length of a list) and give you the number of all boxes in said room.

A simple function, something like this

def get_boxes(room):

tree = ET.parse("filename.xml")
root = tree.getroot()
boxList = []

for rooms in root:
    if rooms.tag == room:
        for boxes in rooms:
            boxList.append(boxes.attrib['name'])

return boxList

You can also get rid of all of those global statements, whenever you want to know the box count you can just call len(get_boxes(roomName)).

Similarly, you don't need a function for every different box you remove, aslong as you can get which box the user is selecting a simple remove function will do, not unlike:

def remove_box(boxName, boxRoom):
tree = ET.parse("filename.xml")
root = tree.getroot()

for rooms in root:
    if rooms.tag == boxRoom:
        for boxes in rooms:
            if boxes.attrib['name'] == boxName:
                rooms.remove(boxes)
                break
            
ET.indent(tree, space = '\t', level=0)
tree.write("filename.xml", "utf-8")

It's the same story for adding a box, you can almost completely reuse a function to add boxes. Pass in the boxes name, which room it will be in, and the function can do the rest

def create_box(boxName, boxRoom):
tree = ET.parse("filename.xml")
root = tree.getroot()

for rooms in root:
    if rooms.tag == boxRoom:
        for boxes in rooms:
            ET.SubElement(boxes, 'box', name = boxName)
            
ET.indent(tree, space = '\t', level=0)
tree.write("filename.xml", "utf-8")

Some other suggestions, I would give the rooms there own names,

ET.SubElement("parent", 'room', name = "Kitchen")

and you can find that name with room.attrib['name'], you could do the same with boxes as well. That way the only two things you really need to collect from the user is what box they have selected and what room they are in.

I'm afraid I can't help you with the TKinter side of things, I always preferred PySimpleGUI, but if you can add and remove boxes, then just adding them into the add and remove functions could be enough.

My code is probably splattered with syntax errors, but I hope this helps.

Python相关问答推荐

基于字符串匹配条件合并两个帧

数据抓取失败:寻求帮助

给定高度约束的旋转角解析求解

Django RawSQL注释字段

实现神经网络代码时的TypeError

如何使用两个关键函数来排序一个多索引框架?

下三角形掩码与seaborn clustermap bug

如何杀死一个进程,我的Python可执行文件以sudo启动?

搜索按钮不工作,Python tkinter

替换现有列名中的字符,而不创建新列

获取PANDA GROUP BY转换中的组的名称

使用polars. pivot()旋转一个框架(类似于R中的pivot_longer)

Pandas:计数器的滚动和,复位

遍历列表列表,然后创建数据帧

如何将列表从a迭代到z-以抓取数据并将其转换为DataFrame?

.awk文件可以使用子进程执行吗?

Pandas:使列中的列表大小与另一列中的列表大小相同

如何批量训练样本大小为奇数的神经网络?

如何定义一个将类型与接收该类型的参数的可调用进行映射的字典?

在Pandas 中,有没有办法让元组作为索引运行得很好?