added code

This commit is contained in:
2026-01-20 12:10:36 +01:00
parent c102728634
commit e64a532ba6

230
xml_extractor.py Normal file
View File

@@ -0,0 +1,230 @@
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import xml.etree.ElementTree as ET
import os
class XMLExtractorApp:
def __init__(self, root):
self.root = root
self.root.title("XML Shape to Symbol Extractor")
self.root.geometry("600x600")
self.root.resizable(False, False)
self.input_file = None
self.tree = None
self.create_widgets()
def create_widgets(self):
# Title
title = tk.Label(self.root, text="XML Shape to Symbol Extractor",
font=("Arial", 16, "bold"))
title.pack(pady=10)
# Info label
info = tk.Label(self.root, text="Extracts from: /layers/layer/shape\nWrites to: /key/kentry/custom/symbol/group/shape",
font=("Arial", 9), fg="gray", justify=tk.CENTER)
info.pack()
# Input file frame
input_frame = tk.Frame(self.root)
input_frame.pack(pady=10, padx=20, fill=tk.X)
tk.Label(input_frame, text="Input LXXPLOT File:",
font=("Arial", 10)).pack(anchor=tk.W)
file_display_frame = tk.Frame(input_frame)
file_display_frame.pack(fill=tk.X, pady=5)
self.file_label = tk.Label(file_display_frame, text="No file selected",
fg="gray", anchor=tk.W)
self.file_label.pack(side=tk.LEFT, fill=tk.X, expand=True)
browse_btn = tk.Button(file_display_frame, text="Browse",
command=self.browse_file)
browse_btn.pack(side=tk.RIGHT)
# Output file frame
output_frame = tk.Frame(self.root)
output_frame.pack(pady=10, padx=20, fill=tk.X)
tk.Label(output_frame, text="Output LXKEY File:",
font=("Arial", 10)).pack(anchor=tk.W)
self.output_entry = tk.Entry(output_frame, font=("Arial", 10))
self.output_entry.pack(fill=tk.X, pady=5)
self.output_entry.insert(0, "symbol_output.lxkey")
# Additional fields frame
fields_frame = tk.Frame(self.root)
fields_frame.pack(pady=10, padx=20, fill=tk.X)
tk.Label(fields_frame, text="Additional Tag Values:",
font=("Arial", 10, "bold")).pack(anchor=tk.W, pady=(0, 5))
# Name field (displayed as "Type")
name_frame = tk.Frame(fields_frame)
name_frame.pack(fill=tk.X, pady=2)
tk.Label(name_frame, text="Type:", width=10, anchor=tk.W).pack(side=tk.LEFT)
self.name_entry = tk.Entry(name_frame, font=("Arial", 10))
self.name_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
# ID field
id_frame = tk.Frame(fields_frame)
id_frame.pack(fill=tk.X, pady=2)
tk.Label(id_frame, text="ID:", width=10, anchor=tk.W).pack(side=tk.LEFT)
self.id_entry = tk.Entry(id_frame, font=("Arial", 10))
self.id_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
# Fname field
fname_frame = tk.Frame(fields_frame)
fname_frame.pack(fill=tk.X, pady=2)
tk.Label(fname_frame, text="Fname:", width=10, anchor=tk.W).pack(side=tk.LEFT)
self.fname_entry = tk.Entry(fname_frame, font=("Arial", 10))
self.fname_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
# Kind field (dropdown)
kind_frame = tk.Frame(fields_frame)
kind_frame.pack(fill=tk.X, pady=2)
tk.Label(kind_frame, text="Kind:", width=10, anchor=tk.W).pack(side=tk.LEFT)
# Dictionary mapping display names to values
self.kind_options = {
"eko / ERS": "ers",
"Zoom Leko / ERS": "zers",
"Fresnel / PC": "fres",
"PAR": "par",
"Flood": "fl",
"Striplight": "strip",
"DMX Device": "scroll",
"Mirror": "mirror",
"Focus Point": "focus",
"Other": "misc",
"Automated Fixture": "mover",
"Color Mixing Automated Fixture": "cmymvr",
"Color Mixing Rectangular Beam (obsolete rgb)": "rgb",
"Color Mixing Rectangular Beam (obsolete rgba)": "rgba",
"Color Mixing Rectangular Beam": "led7",
"Color Mixing Striplight": "led7s",
"Color Mixing Leko / ERS": "cmers",
"Color Mixing Zoom ERS": "cmzers",
"Color Mixing DMX Device": "cmscroll",
"Network Device": "netnode"
}
self.kind_var = tk.StringVar()
self.kind_dropdown = ttk.Combobox(kind_frame, textvariable=self.kind_var,
values=list(self.kind_options.keys()),
state="readonly",
font=("Arial", 10))
self.kind_dropdown.pack(side=tk.LEFT, fill=tk.X, expand=True)
self.kind_dropdown.current(0) # Set default to first option
# Extract button
extract_btn = tk.Button(self.root, text="Extract and Convert",
command=self.extract_and_convert,
font=("Arial", 12, "bold"),
bg="#4CAF50", fg="white",
padx=20, pady=10)
extract_btn.pack(pady=20)
# Status label
self.status_label = tk.Label(self.root, text="",
font=("Arial", 9), fg="blue")
self.status_label.pack(pady=5)
def browse_file(self):
filename = filedialog.askopenfilename(
title="Select LXXPLOT File",
filetypes=[("LXXPLOT files", "*.lxxplot"), ("All files", "*.*")]
)
if filename:
self.input_file = filename
self.file_label.config(text=os.path.basename(filename), fg="black")
self.status_label.config(text="File loaded successfully", fg="green")
def extract_and_convert(self):
# Validate inputs
if not self.input_file:
messagebox.showerror("Error", "Please select an input LXXPLOT file")
return
output_filename = self.output_entry.get().strip()
if not output_filename:
messagebox.showerror("Error", "Please enter an output file name")
return
# Get the directory of the input file and create full output path
input_dir = os.path.dirname(self.input_file)
output_file = os.path.join(input_dir, output_filename)
try:
# Parse the LXXPLOT file (XML format)
tree = ET.parse(self.input_file)
root = tree.getroot()
# Find the shape tag using the xpath: /layers/layer/shape
shape_element = root.find("./layers/layer/shape")
if shape_element is None:
messagebox.showerror("Error",
"Path '/layers/layer/shape' not found in the LXXPLOT file")
return
# Create the new XML structure: /key/kentry/custom/symbol/group/shape
new_root = ET.Element("key")
kentry = ET.SubElement(new_root, "kentry")
# Add name, kind, and fname as siblings of custom with user-provided values
name = ET.SubElement(kentry, "name")
name.text = self.name_entry.get().strip()
id_elem = ET.SubElement(kentry, "id")
id_elem.text = self.id_entry.get().strip()
kind = ET.SubElement(kentry, "kind")
# Get the value corresponding to the selected display name
selected_display = self.kind_var.get()
kind.text = self.kind_options.get(selected_display, "")
fname = ET.SubElement(kentry, "fname")
fname.text = self.fname_entry.get().strip()
custom = ET.SubElement(kentry, "custom")
symbol = ET.SubElement(custom, "symbol")
group = ET.SubElement(symbol, "group")
shape = ET.SubElement(group, "shape")
# Copy the content from shape element to the new shape element
shape.text = shape_element.text
shape.attrib = shape_element.attrib
# Copy all child elements from original shape to new shape
for child in shape_element:
shape.append(child)
# Create and write the new LXKEY file
new_tree = ET.ElementTree(new_root)
ET.indent(new_tree, space=" ")
new_tree.write(output_file, encoding="utf-8", xml_declaration=True)
self.status_label.config(
text=f"Successfully converted and saved to {output_filename}",
fg="green"
)
messagebox.showinfo("Success",
f"Shape content extracted and written to /key/kentry/custom/symbol/group/shape\nSaved to: {output_file}")
except ET.ParseError as e:
messagebox.showerror("Parse Error",
f"Failed to parse XML file:\n{str(e)}")
self.status_label.config(text="Parse error", fg="red")
except Exception as e:
messagebox.showerror("Error", f"An error occurred:\n{str(e)}")
self.status_label.config(text="Error occurred", fg="red")
if __name__ == "__main__":
root = tk.Tk()
app = XMLExtractorApp(root)
root.mainloop()