import sys sys.modules["_elementtree"] = None import xml.etree.ElementTree as ET import os from pathlib import Path items = {} # stolen from https://stackoverflow.com/a/36430270 class LineNumberingParser(ET.XMLParser): def _start(self, *args, **kwargs): # Here we assume the default XML parser which is expat # and copy its element position attributes into output Elements element = super(self.__class__, self)._start(*args, **kwargs) element._start_line_number = self.parser.CurrentLineNumber element._start_column_number = self.parser.CurrentColumnNumber element._start_byte_index = self.parser.CurrentByteIndex return element def _end(self, *args, **kwargs): element = super(self.__class__, self)._end(*args, **kwargs) element._end_line_number = self.parser.CurrentLineNumber element._end_column_number = self.parser.CurrentColumnNumber element._end_byte_index = self.parser.CurrentByteIndex return element def convertMonster(path, name, outPath): path = os.path.join(path, name) if not os.path.exists(path): print("Couldn't find xml file at path {}", path) return print("Converting {}".format(name)) root = ET.parse(path, parser=LineNumberingParser(target=ET.TreeBuilder(insert_comments=True))).getroot() loot = root.find("loot") if loot is None: return commentsLines = {} for child in loot: item_name = child.attrib.get("name") id = child.attrib.get("id") if item_name is None or id is not None: continue child.attrib.pop("name") id = items.get(item_name.lower()) if id is None: continue # trickery to add new attribute as the first attribute, google didn't tell me how to do this in etree :( copy = list(child.attrib.items()) copy.insert(0, ("id", id)) child.attrib = dict(copy) # store to add item name comments commentsLines[child._start_line_number - 1] = item_name # dont ask me why it counts lines wrong, but - 1 fixes it, probably declaration? outFile = os.path.join(outPath, name) # save to file ET.ElementTree(root).write(os.path.join(outPath, name), encoding='utf-8', xml_declaration=True) # add comments with item name with open(outFile, "r") as f: lines = f.readlines() lines.append("\n") for key, value in commentsLines.items(): lines[key] = "{} \n".format(lines[key].rstrip("\n"), value) with open(outFile, "w") as f: f.writelines(lines) def convertMonsters(path): path = Path(path).resolve() if not os.path.exists(path): exit("Unable to resolve monsters directory, aborting...") print("Resolved monsters path {}".format(path)) outPath = os.path.join(Path(input("Out directory path (if out not present will create one)")).resolve(), "out") # ensure out directory is present if not os.path.exists(outPath): os.makedirs(outPath) print("Resolved output path {}".format(outPath)) # convert for file in os.listdir(path): if file.endswith(".xml"): convertMonster(path, file, outPath) def readItems(path): path = os.path.join(Path(path).resolve(), "items.xml") if not os.path.exists(path): exit('Unable to find items.xml in given path, aborting...') print("Resolved items path {}".format(path)) root = ET.parse(path).getroot() for elem in root: name = elem.attrib.get("name") id = elem.attrib.get("id") if name is None or id is None: continue items[name.lower()] = id if __name__ == "__main__": # read items first readItems(input("Path to items directory: ")) # monsters convertMonsters(input("Path to monster directory: "))