Insert Element In XML File by Python xml.etree.ElementTree Module

本文介绍了一个使用Python的xml.etree.ElementTree模块来实现在XML文件中插入元素的简单示例。通过解析XML文件,创建新的policy元素并将其插入到指定位置,最后将更改写回XML文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

This is a simple exmple to insert an element in XML file by python xml.etree.ElmentTree Module.

 

sample.xml

 

 

 

python script.

 

 

After run the script, the xml file likes below.

 

对以下代码进行拆分,自动识别功能项,拆分到多个文件中,避免单个文件过长,不能影响功能使用import tkinter as tk from tkinter import ttk, filedialog, messagebox, scrolledtext #import xml.etree.ElementTree as ET from lxml import etree as ET import os import re from xml.dom import minidom from collections import OrderedDict, defaultdict class ConfigUpdaterApp: def __init__(self, root): self.root = root self.root.title("ID统一配置文件自动更新工具") self.root.geometry("1920x1080") self.root.configure(bg="#f0f0f0") # 创建样式 self.style = ttk.Style() self.style.configure("TButton", padding=6, relief="flat", background="#4a7a8c", foreground="blue") self.style.configure("Treeview", font=("Consolas", 10), rowheight=25) self.style.configure("Treeview.Heading", font=("Arial", 11, "bold")) self.style.configure("TNotebook", background="#f0f0f0") self.style.configure("TNotebook.Tab", padding=(10, 5), font=("Arial", 10, "bold")) self.style.configure("XMLText", font=("Consolas", 10), background="#f8f8f8") # 创建主框架 self.create_widgets() # 初始化数据结构 self.rawdata_template = [] self.rawdata_source = None self.event_template = [] self.event_source = None self.current_filter = "" self.variable_mapping = {} self.module_mapping = {} self.init_module() self.event_categories = [] def init_module(self): """ 初始化moduleID与SVEC模板中一致 :return: """ self.module_mapping["System"] = "00" self.module_mapping["EFEM"] = "01" self.module_mapping["Transfer"] = "02" self.module_mapping["Buffer"] = "03" self.module_mapping["LA"] = "11" self.module_mapping["LB"] = "12" self.module_mapping["LC"] = "13" self.module_mapping["LD"] = "14" self.module_mapping["LAB"] = "15" self.module_mapping["LCD"] = "16" self.module_mapping["Ch1"] = "21" self.module_mapping["Ch2"] = "22" self.module_mapping["Ch3"] = "23" self.module_mapping["Ch4"] = "24" self.module_mapping["Ch5"] = "25" self.module_mapping["Ch6"] = "26" self.module_mapping["ChA"] = "27" self.module_mapping["ChB"] = "28" self.module_mapping["ChC"] = "29" self.module_mapping["ChD"] = "30" self.module_mapping["ChE"] = "31" self.module_mapping["ChF"] = "32" def get_module_id(self, module_name): """ 根据module_name和映射表获取id :param module_name: :return: """ if module_name not in self.module_mapping: return None else: return self.module_mapping[module_name] def create_widgets(self): """创建界面组件""" # 创建选项卡 self.notebook = ttk.Notebook(self.root) self.notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # RawdataConfig 标签页 self.rawdata_frame = ttk.Frame(self.notebook) self.notebook.add(self.rawdata_frame, text="RawdataConfig") self.create_rawdata_tab(self.rawdata_frame) # EventConfig 标签页 self.event_frame = ttk.Frame(self.notebook) self.notebook.add(self.event_frame, text="EventConfig") self.create_event_tab(self.event_frame) # 状态栏 self.status_var = tk.StringVar(value="就绪") status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W, padding=5) status_bar.pack(side=tk.BOTTOM, fill=tk.X) def create_rawdata_tab(self, parent): """创建RawdataConfig标签页""" # 顶部按钮区域 btn_frame = ttk.Frame(parent) btn_frame.pack(fill=tk.X, padx=10, pady=10) # RawdataConfig 按钮 ttk.Button(btn_frame, text="1.加载模板文件", command=self.load_rawdata_template).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="2.加载源文件", command=self.load_rawdata_source).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="3.新增ID属性", command=self.add_id_to_rawdata).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="4.筛选模板Variable", command=self.filter_template_vars).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="5.筛选源文件Variable", command=self.filter_source_vars).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="6.对比", command=self.compare_vars).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="7.导出标红内容", command=self.export_highlighted).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="8.填充ID属性", command=self.fill_ids).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="9.删除空ID节点", command=self.filter_empty_id_nodes).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="10.导出文件", command=self.export_rawdata).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="11.拆分文件并导出", command=self.split_export).pack(side=tk.LEFT, padx=5) # 创建分割面板 paned_window = ttk.PanedWindow(parent, orient=tk.VERTICAL) paned_window.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10)) # 上半部分 - 模板显示 template_frame = ttk.LabelFrame(paned_window, text="模板显示") paned_window.add(template_frame, weight=1) # 模板表格 self.create_template_table(template_frame) # 下半部分 - 源文件显示(XML原始格式) source_frame = ttk.LabelFrame(paned_window, text="源文件显示(XML原始格式)") paned_window.add(source_frame, weight=1) # XML文本显示区域 self.rawdata_xml_text = scrolledtext.ScrolledText( source_frame, wrap=tk.WORD, font=("Consolas", 10), bg="#f8f8f8", padx=10, pady=10 ) self.rawdata_xml_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.rawdata_xml_text.config(state=tk.DISABLED) # 初始为只读 # 底部筛选区域 filter_frame = ttk.Frame(parent) filter_frame.pack(fill=tk.X, padx=10, pady=(0, 10)) # 模板Variable筛选 ttk.Label(filter_frame, text="模板Variable筛选:").pack(side=tk.LEFT, padx=(0, 5)) self.template_filter_var = tk.StringVar() self.template_filter_box = tk.Listbox(filter_frame, listvariable=self.template_filter_var, height=6, width=30, selectmode=tk.EXTENDED) self.template_filter_box.pack(side=tk.LEFT, padx=5, pady=5, fill=tk.BOTH, expand=True) # 源文件Variable筛选 ttk.Label(filter_frame, text="源文件Variable筛选:").pack(side=tk.LEFT, padx=(20, 5)) self.source_filter_var = tk.StringVar() self.source_filter_box = tk.Listbox(filter_frame, listvariable=self.source_filter_var, height=6, width=30, selectmode=tk.EXTENDED) self.source_filter_box.pack(side=tk.LEFT, padx=5, pady=5, fill=tk.BOTH, expand=True) # 对比结果区域 self.compare_result = tk.Text(filter_frame, height=6, width=30, state=tk.DISABLED) self.compare_result.pack(side=tk.LEFT, padx=5, pady=5, fill=tk.BOTH, expand=True) def create_event_tab(self, parent): """创建EventConfig标签页""" # 顶部按钮区域 btn_frame = ttk.Frame(parent) btn_frame.pack(fill=tk.X, padx=10, pady=10) # EventConfig 按钮 ttk.Button(btn_frame, text="1.加载模板文件", command=self.load_event_template).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="2.加载源文件", command=self.load_event_source).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="3.新增ID属性", command=self.add_id_to_event).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="4.填充ID属性", command=self.fill_event_attributes).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="5.导出文件", command=self.export_event).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="6.拆分文件并导出", command=self.split_export_event).pack(side=tk.LEFT, padx=5) # 创建分割面板 paned_window = ttk.PanedWindow(parent, orient=tk.VERTICAL) paned_window.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10)) # 上半部分 - 模板显示 template_frame = ttk.LabelFrame(paned_window, text="模板显示") paned_window.add(template_frame, weight=1) # 模板表格 self.create_event_template_table(template_frame) # 下半部分 - 源文件显示(XML原始格式) source_frame = ttk.LabelFrame(paned_window, text="源文件显示(XML原始格式)") paned_window.add(source_frame, weight=1) # XML文本显示区域 self.event_xml_text = scrolledtext.ScrolledText( source_frame, wrap=tk.WORD, font=("Consolas", 10), bg="#f8f8f8", padx=10, pady=10 ) self.event_xml_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.event_xml_text.config(state=tk.DISABLED) # 初始为只读 def create_template_table(self, parent): """创建Rawdata模板表格""" # 创建滚动条 scroll_y = ttk.Scrollbar(parent, orient=tk.VERTICAL) scroll_x = ttk.Scrollbar(parent, orient=tk.HORIZONTAL) # 创建Treeview表格 columns = ("name", "type", "variable", "id") self.template_table = ttk.Treeview( parent, columns=columns, show="headings", yscrollcommand=scroll_y.set, xscrollcommand=scroll_x.set, selectmode="extended" ) # 配置列标题 self.template_table.heading("name", text="Name", anchor=tk.W) self.template_table.heading("type", text="Type", anchor=tk.W) self.template_table.heading("variable", text="Variable", anchor=tk.W) self.template_table.heading("id", text="ID", anchor=tk.W) # 配置列宽度 self.template_table.column("name", width=150, anchor=tk.W) self.template_table.column("type", width=120, anchor=tk.W) self.template_table.column("variable", width=300, anchor=tk.W) self.template_table.column("id", width=100, anchor=tk.W) # 配置滚动条 scroll_y.config(command=self.template_table.yview) scroll_x.config(command=self.template_table.xview) # 布局 self.template_table.grid(row=0, column=0, sticky="nsew") scroll_y.grid(row=0, column=1, sticky="ns") scroll_x.grid(row=1, column=0, sticky="ew") # 配置网格权重 parent.grid_rowconfigure(0, weight=1) parent.grid_columnconfigure(0, weight=1) def create_event_template_table(self, parent): """创建Event模板表格""" # 创建滚动条 scroll_y = ttk.Scrollbar(parent, orient=tk.VERTICAL) scroll_x = ttk.Scrollbar(parent, orient=tk.HORIZONTAL) # 创建Treeview表格 columns = ("name", "id", "type") self.event_template_table = ttk.Treeview( parent, columns=columns, show="headings", yscrollcommand=scroll_y.set, xscrollcommand=scroll_x.set, selectmode="extended" ) # 配置列标题 self.event_template_table.heading("name", text="Name", anchor=tk.W) self.event_template_table.heading("id", text="ID", anchor=tk.W) self.event_template_table.heading("type", text="Type", anchor=tk.W) # 配置列宽度 self.event_template_table.column("name", width=100, anchor=tk.W) self.event_template_table.column("id", width=100, anchor=tk.W) self.event_template_table.column("type", width=100, anchor=tk.W) # 配置滚动条 scroll_y.config(command=self.event_template_table.yview) scroll_x.config(command=self.event_template_table.xview) # 布局 self.event_template_table.grid(row=0, column=0, sticky="nsew") scroll_y.grid(row=0, column=1, sticky="ns") scroll_x.grid(row=1, column=0, sticky="ew") # 配置网格权重 parent.grid_rowconfigure(0, weight=1) parent.grid_columnconfigure(0, weight=1) def display_xml_content(self, xml_tree, text_widget): """在文本框中显示格式化的XML内容""" try: # 将XML树转换为字符串 xml_str = ET.tostring(xml_tree.getroot(), encoding='utf-8').decode('utf-8') # 使用minidom进行格式化 dom = minidom.parseString(xml_str) pretty_xml = dom.toprettyxml(indent=" ") # 移除多余的换行 pretty_xml = "\n".join([line for line in pretty_xml.split("\n") if line.strip()]) # 更新文本框 text_widget.config(state=tk.NORMAL) text_widget.delete(1.0, tk.END) text_widget.insert(tk.END, pretty_xml) text_widget.config(state=tk.DISABLED) # 高亮空ID节点(可选) self.highlight_empty_id_nodes(text_widget, pretty_xml) except Exception as e: messagebox.showerror("显示错误", f"格式化XML显示失败: {str(e)}") def highlight_empty_id_nodes(self, text_widget, xml_content): """高亮显示id为空的data节点""" if not xml_content: return # 查找所有id属性为空的data节点 pattern = r'(<data\b[^>]*\bid="")' matches = re.finditer(pattern, xml_content) # 设置高亮样式 text_widget.tag_configure("empty_id", background="#ffe6e6") # 应用高亮 for match in matches: start_index = f"1.0 + {match.start()} chars" end_index = f"1.0 + {match.end()} chars" text_widget.tag_add("empty_id", start_index, end_index) # ================ RawdataConfig 功能 ================ def load_rawdata_template(self): """加载Rawdata模板文件(.txt)""" file_path = filedialog.askopenfilename( title="选择Rawdata模板文件", filetypes=[("Text files", "*.txt"), ("All files", "*.*")] ) if not file_path: return try: with open(file_path, 'r', encoding='utf-8') as file: lines = file.readlines() self.rawdata_template = [] # 清空表格 for item in self.template_table.get_children(): self.template_table.delete(item) # 解析模板文件 for line in lines: line = line.strip() if not line: continue # 分割行数据 parts = line.split() if len(parts) < 4: continue # 提取前四列 name = parts[0] var_type = parts[1] variable = parts[2] var_id = parts[3] if len(parts) > 3 else "" self.rawdata_template.append({ "name": name, "type": var_type, "variable": variable, "id": var_id }) # 添加到表格 self.template_table.insert("", tk.END, values=(name, var_type, variable, var_id)) self.status_var.set(f"已加载Rawdata模板: {os.path.basename(file_path)} - {len(self.rawdata_template)} 条记录") except Exception as e: messagebox.showerror("加载错误", f"加载Rawdata模板文件失败: {str(e)}") def load_rawdata_source(self): """加载Rawdata源文件(.xml)""" file_path = filedialog.askopenfilename( title="选择Rawdata源文件", filetypes=[("XML files", "*.xml"), ("All files", "*.*")] ) if not file_path: return try: self.rawdata_tree = ET.parse(file_path) self.rawdata_root = self.rawdata_tree.getroot() self.rawdata_source = self.rawdata_tree # 在文本框中显示XML内容 self.display_xml_content(self.rawdata_tree, self.rawdata_xml_text) self.status_var.set(f"已加载Rawdata源文件: {os.path.basename(file_path)}") except Exception as e: messagebox.showerror("加载错误", f"加载Rawdata源文件失败: {str(e)}") def add_id_to_rawdata(self): """为Rawdata源文件添加ID属性""" if not self.rawdata_source: messagebox.showwarning("无数据", "请先加载Rawdata源文件") return # 添加ID属性 count = 0 for data in self.rawdata_root.findall('.//data'): if 'id' not in data.attrib: # 在属性开头位置添加id属性 new_attrib = OrderedDict() new_attrib['id'] = '' for key, value in data.attrib.items(): new_attrib[key] = value #data.attrib = new_attrib data.attrib.clear() for key, value in new_attrib.items(): data.set(key, value) count += 1 # 更新XML显示 self.display_xml_content(self.rawdata_tree, self.rawdata_xml_text) self.status_var.set(f"已为{count}个data标签添加id属性") def filter_template_vars(self): """筛选模板Variable""" if not self.rawdata_template: messagebox.showwarning("无数据", "请先加载Rawdata模板文件") return # 提取Variable后半部分并去重 var_parts = set() for item in self.rawdata_template: variable = item["variable"] parts = variable.split('_', 1) # 只分割第一个下划线 if len(parts) > 1: var_parts.add(parts[1]) # 更新列表 self.template_filter_var.set(tuple(sorted(var_parts))) self.status_var.set(f"已筛选出 {len(var_parts)} 个模板Variable") def filter_source_vars(self): """筛选源文件Variable""" if not self.rawdata_source: messagebox.showwarning("无数据", "请先加载Rawdata源文件") return # 提取Variable后半部分并去重 var_parts = set() for data in self.rawdata_root.findall('.//data'): variable = data.get('variable', '') if variable: parts = variable.split('_', 1) # 只分割第一个下划线 if len(parts) > 1: var_parts.add(parts[1]) # 更新列表 self.source_filter_var.set(tuple(sorted(var_parts))) self.status_var.set(f"已筛选出 {len(var_parts)} 个源文件Variable") def compare_vars(self): """对比模板和源文件Variable""" template_vars = self.template_filter_box.get(0, tk.END) source_vars = self.source_filter_box.get(0, tk.END) if not template_vars or not source_vars: messagebox.showwarning("无数据", "请先筛选模板和源文件Variable") return # 清空对比结果 self.compare_result.config(state=tk.NORMAL) self.compare_result.delete(1.0, tk.END) # 查找源文件中有但模板中没有的Variable missing_in_template = set(source_vars) - set(template_vars) # 更新源文件列表,标红缺失项 self.source_filter_box.delete(0, tk.END) for var in sorted(source_vars): self.source_filter_box.insert(tk.END, var) if var in missing_in_template: self.source_filter_box.itemconfig(tk.END, fg='red') # 显示对比结果 self.compare_result.insert(tk.END, "对比结果:\n") self.compare_result.insert(tk.END, f"模板Variable数量: {len(template_vars)}\n") self.compare_result.insert(tk.END, f"源文件Variable数量: {len(source_vars)}\n") self.compare_result.insert(tk.END, f"源文件中有但模板中缺失的数量: {len(missing_in_template)}\n\n") if missing_in_template: self.compare_result.insert(tk.END, "缺失的Variable:\n") for var in sorted(missing_in_template): self.compare_result.insert(tk.END, f" - {var}\n") self.compare_result.config(state=tk.DISABLED) self.status_var.set(f"对比完成: 发现 {len(missing_in_template)} 个缺失项") def export_highlighted(self): """导出标红内容""" # 获取标红的项 highlighted_items = [] for i in range(self.source_filter_box.size()): if self.source_filter_box.itemcget(i, "fg") == "red": highlighted_items.append(self.source_filter_box.get(i)) if not highlighted_items: messagebox.showinfo("无数据", "没有标红的项可导出") return # 选择保存位置 file_path = filedialog.asksaveasfilename( title="保存标红内容", defaultextension=".txt", filetypes=[("Text files", "*.txt"), ("All files", "*.*")] ) if not file_path: return # 写入文件 try: with open(file_path, 'w', encoding='utf-8') as file: file.write("标红的Variable项:\n") for item in highlighted_items: file.write(f"{item}\n") self.status_var.set(f"已导出 {len(highlighted_items)} 个标红项到 {os.path.basename(file_path)}") messagebox.showinfo("导出成功", "标红项已成功导出") except Exception as e: messagebox.showerror("导出错误", f"导出文件失败: {str(e)}") def fill_ids(self): """填充ID属性(占位)""" if not self.rawdata_source: messagebox.showwarning("无数据", "请先加载Rawdata源文件") return if not self.rawdata_root: messagebox.showwarning("无数据", "请先加载Rawdata源文件") return if not self.rawdata_template: messagebox.showwarning("无数据", "请先加载模板文件") return # 自动加载映射表,如果不存在就不加载 self.init_variable_mapping() fill_count = 0 not_exist = [] not_exist_all = [] for data_elem in self.rawdata_tree.findall('.//data'): variable = data_elem.get('variable') parts = variable.split('_', 1) if len(parts) < 2: continue module = parts[0] var = parts[1] temp_var, temp_id = self.get_id(module, var) if temp_var and temp_id: data_elem.set('variable', temp_var) data_elem.set('id', temp_id) fill_count += 1 else: if temp_id is None and var not in not_exist: not_exist.append(var) if temp_id is None: not_exist_all.append(variable) # 更新XML显示 self.display_xml_content(self.rawdata_tree, self.rawdata_xml_text) self.status_var.set(f"已为{fill_count}个data标签添加id属性,剩余{len(not_exist)}无对应值。总共剩余{len(not_exist_all)}个未设置") #messagebox.showinfo("功能待实现", "填充ID属性功能将在后续版本实现") def filter_empty_id_nodes(self): """删除id属性为空的data节点并刷新显示""" if not self.rawdata_source: messagebox.showwarning("无数据", "请先加载Rawdata源文件") return # 获取XML根节点 root = self.rawdata_tree.getroot() # 确保获取根节点[^5] # 查找所有id属性为空的data节点 empty_id_nodes = [] for data_node in root.iter('data'): if data_node.get('id', '') == '': empty_id_nodes.append(data_node) if not empty_id_nodes: messagebox.showinfo("无操作", "未找到id为空的data节点") return # 删除这些节点(使用替代方法获取父节点) for node in empty_id_nodes: # 替代 getparent() 的方法 for parent in root.iter(): if node in list(parent): # 检查节点是否是当前父节点的直接子节点 parent.remove(node) break # 刷新XML显示 self.display_xml_content(self.rawdata_tree, self.rawdata_xml_text) # 更新状态 self.status_var.set(f"已删除 {len(empty_id_nodes)} 个id为空的data节点") def export_rawdata(self): """导出Rawdata源文件""" if not self.rawdata_source: messagebox.showwarning("无数据", "没有可导出的数据") return file_path = filedialog.asksaveasfilename( title="保存Rawdata文件", defaultextension=".xml", filetypes=[("XML files", "*.xml"), ("All files", "*.*")] ) if not file_path: return try: # 使用minidom美化输出 ''' xml_str = ET.tostring(self.rawdata_root, encoding='utf-8').decode('utf-8') parsed = minidom.parseString(xml_str) pretty_xml = parsed.toprettyxml(indent=" ") # 写入文件 with open(file_path, 'w', encoding='utf-8') as file: file.write(pretty_xml) ''' self.rawdata_tree.write(file_path, encoding='utf-8', xml_declaration=True) self.status_var.set(f"Rawdata文件已成功导出到: {os.path.basename(file_path)}") messagebox.showinfo("导出成功", "Rawdata配置文件已成功导出") except Exception as e: messagebox.showerror("导出错误", f"导出文件失败: {str(e)}") def init_variable_mapping(self): with open('SV_mapping.txt', 'r') as file: for line in file.readlines(): parts = line.split() if len(parts) == 2: self.variable_mapping[parts[0]] = parts[1] def get_id(self, module_name, var): if var in self.variable_mapping: var = self.variable_mapping[var] temp_var = "CHXXX_" + var module_id = self.get_module_id(module_name) variable = module_name + '_' + var # Ch1_LotID temp_id = self.get_id_by_variable(temp_var) if temp_id and module_id: id = temp_id.replace('XX', str(module_id)) return variable, id else: return None, None def get_id_by_variable(self, variable): for item in self.rawdata_template: if item['variable'] == variable: return item['id'] def split_export(self): if not self.rawdata_source: messagebox.showwarning("无数据", "没有可拆分的数据") return # 创建分组字典,前缀为data节点列表 groups = defaultdict(list) # 遍历所有data节点 for data in self.rawdata_root.findall('.//data'): variable = data.get('variable','') if '_' in variable: prefix = variable.split('_', 1)[0] groups[prefix].append(data) # 为每个分组创建新的xml文件 for prefix, data in groups.items(): # 创建新根节点(复制原始根节点标签和属性) new_root = ET.Element(self.rawdata_root.tag, attrib=self.rawdata_root.attrib) # 复制原始根节点的命名空间 # 复制原始根节点的命名空间 for ns, uri in self.rawdata_root.nsmap.items(): if ns: ET.register_namespace(ns, uri) # 添加原始非 data 节点 for child in self.rawdata_root: if child.tag != 'data': new_root.append(child) # 添加分组中的 data 节点 for node in data: new_root.append(node) # 创建 XML 树并写入文件 new_tree = ET.ElementTree(new_root) filename = f"RawData_{prefix}.xml" new_tree.write(filename, encoding='utf-8', xml_declaration=True) return # ================ EventConfig 功能 ================ def load_event_template(self): """加载Event模板文件(.txt)""" file_path = filedialog.askopenfilename( title="选择Event模板文件", filetypes=[("Text files", "*.txt"), ("All files", "*.*")] ) if not file_path: return try: with open(file_path, 'r', encoding='utf-8') as file: lines = file.readlines() self.event_template = [] # 清空表格 for item in self.event_template_table.get_children(): self.event_template_table.delete(item) # 解析模板文件 for line in lines: line = line.strip() if not line: continue # 分割行数据 parts = line.split() if len(parts) < 2: continue # 提取前两列 name = parts[0] event_id = parts[1] if len(parts) > 1 else "" # 提取type name_parts = name.split('_',1) if len(name_parts) < 2: continue type = name_parts[1] self.event_categories.append(type) self.event_template.append({ "name": name, "id": event_id, "type": type }) # 添加到表格 self.event_template_table.insert("", tk.END, values=(name, event_id, type)) self.event_categories = sorted(self.event_categories, key=len, reverse=True) self.status_var.set(f"已加载Event模板: {os.path.basename(file_path)} - {len(self.event_template)} 条记录") except Exception as e: messagebox.showerror("加载错误", f"加载Event模板文件失败: {str(e)}") def load_event_source(self): """加载Event源文件(.xml)""" file_path = filedialog.askopenfilename( title="选择Event源文件", filetypes=[("XML files", "*.xml"), ("All files", "*.*")] ) if not file_path: return try: self.event_tree = ET.parse(file_path) self.event_root = self.event_tree.getroot() self.event_source = self.event_tree # 在文本框中显示XML内容 self.display_xml_content(self.event_tree, self.event_xml_text) self.status_var.set(f"已加载Event源文件: {os.path.basename(file_path)}") except Exception as e: messagebox.showerror("加载错误", f"加载Event源文件失败: {str(e)}") def add_id_to_event(self): """为Event源文件添加ID属性""" if not self.event_source: messagebox.showwarning("无数据", "请先加载Event源文件") return # 添加ID属性 count = 0 for event in self.event_root.findall('.//event'): if 'id' not in event.attrib: # 在属性开头位置添加id属性 new_attrib = OrderedDict() new_attrib['id'] = '' for key, value in event.attrib.items(): new_attrib[key] = value # data.attrib = new_attrib event.attrib.clear() for key, value in new_attrib.items(): event.set(key, value) count += 1 # 更新XML显示 self.display_xml_content(self.event_tree, self.event_xml_text) self.status_var.set(f"已为{count}个event元素添加ID属性") def get_id_from_event_template(self, event): for item in self.event_template: if item['name'] == event: return item['id'] def get_id_event(self, module, cat): temp_name = "CHXXX_" + cat module_id = self.get_module_id(module) temp_id = self.get_id_from_event_template(temp_name) name = module + '_' + cat if temp_id and module_id: id = temp_id.replace('XX', str(module_id)) return name, id else: return None, None def split_by_type(self, event_name): if not self.event_categories: return for cat in self.event_categories: if event_name.endswith(cat): print('split_by_type:' + cat +'orign:' + event_name) module = event_name[:-len(cat)] return module, cat def fill_event_attributes(self): """填充Event属性(占位)""" # messagebox.showinfo("功能待实现", "填充属性功能将在后续版本实现") # 加载映射表 待实现 if not self.event_source: messagebox.showwarning("无数据", "请先加载EventConfig源文件") return if not self.event_template: messagebox.showwarning("无数据", "请先加载EventConfig模板文件") return fill_count = 0 not_exist = [] not_exist_all = [] for data_elem in self.event_tree.findall('.//event'): name = data_elem.get('name') module, cat = self.split_by_type(name) print('module:'+module+'cat:'+cat) temp_name, temp_id = self.get_id_event(module, cat) #print('temp_name:'+temp_name+' temp_id:'+temp_id) if temp_name and temp_id: data_elem.set('name', temp_name) data_elem.set('id', temp_id) fill_count += 1 else: if temp_id is None and cat not in not_exist: not_exist.append(cat) if temp_id is None: not_exist_all.append(name) self.display_xml_content(self.event_tree, self.event_xml_text) self.status_var.set(f"已为{fill_count}个event补充id属性,剩余{len(not_exist)}个不在模板中,总共剩余{len(not_exist_all)}个") def export_event(self): """导出Event源文件""" if not self.event_source: messagebox.showwarning("无数据", "没有可导出的数据") return file_path = filedialog.asksaveasfilename( title="保存Event文件", defaultextension=".xml", filetypes=[("XML files", "*.xml"), ("All files", "*.*")] ) if not file_path: return try: self.event_tree.write(file_path, encoding='utf-8', xml_declaration=True) self.status_var.set(f"Event文件已成功导出到: {os.path.basename(file_path)}") messagebox.showinfo("导出成功", "Event配置文件已成功导出") except Exception as e: messagebox.showerror("导出错误", f"导出文件失败: {str(e)}") def split_export_event(self): return if __name__ == "__main__": root = tk.Tk() app = ConfigUpdaterApp(root) root.mainloop()
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值