168 lines
6.9 KiB
Python
Executable File
168 lines
6.9 KiB
Python
Executable File
from lib2to3.pgen2.parse import ParseError
|
|
from xml.etree import ElementTree as ET
|
|
import os
|
|
import argparse
|
|
import copy
|
|
|
|
|
|
# Duplicate the Item with the given filename value replacing filename value
|
|
dataFiles = ".//dataFiles/Item/filename/[.='{file}']" # /filename
|
|
|
|
# Duplicate the Item with the given Item value replacing Item value
|
|
filesToInvalidate = ".//contentChangeSets/Item/filesToInvalidate/Item/[.='{file}']"
|
|
|
|
# Duplicate the Item with the given Item value replacing Item value
|
|
filesToEnable = ".//contentChangeSets/Item/filesToEnable/Item/[.='{file}']"
|
|
|
|
# Duplicate the Item with the given Item value replacing Item value
|
|
filesToDisable = ".//contentChangeSets/Item/filesToDisable/Item/[.='{file}']"
|
|
|
|
# Duplicate the Item with the given Item value replacing Item value
|
|
mapfilesToInvalidate = ".//contentChangeSets/Item/mapChangeSetData/Item/filesToInvalidate/Item/[.='{file}']"
|
|
|
|
# Duplicate the Item with the given Item value replacing Item value
|
|
mapfilesToEnable = ".//contentChangeSets/Item/mapChangeSetData/Item/filesToEnable/Item/[.='{file}']"
|
|
|
|
# Duplicate the Item with the given Item value replacing Item value
|
|
mapfilesToDisable = ".//contentChangeSets/Item/mapChangeSetData/Item/filesToDisable/Item/[.='{file}']"
|
|
|
|
changeset_paths = [filesToInvalidate, filesToEnable, filesToDisable, mapfilesToInvalidate, mapfilesToEnable, mapfilesToDisable]
|
|
|
|
# class doop:
|
|
# pass
|
|
|
|
# args = doop()
|
|
# args.in_file = "content.xml"
|
|
# args.copy_insert = "dlc_lev_des.rpf,dlc_lev_des_bvh.rpf,dlc_lev_des_bvh.rpf,dlc_lev_des_doop.rpf"
|
|
# args.insert = "dlc_lev_des_bvh.rpf"
|
|
# args.out_file = "dupe.xml"
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-i", '--in_file', metavar='IN', type=str, required=True,
|
|
help='The input file "IN", used to parse for file entries and insertions if out_file is supplied. e.g. path/to/content.xml')
|
|
|
|
parser.add_argument("-c", '--copy_insert', metavar='CP,INS,...', type=str, required=True,
|
|
help='The file to be copied "CP" followed by the file to insert "INS", within the content.xml document. e.g. copy.rpf,insert.rpf')
|
|
|
|
parser.add_argument("-o", '--out_file', metavar='OUT', type=str, required=True,
|
|
help='The output file "OUT", if not set input file is used. e.g. path/to/content.xml')
|
|
|
|
args = parser.parse_args()
|
|
|
|
if not os.path.exists(args.in_file):
|
|
print("Error: in_file '"+args.in_file+"' doesn't exist")
|
|
exit(1)
|
|
print("Begin parsing "+args.in_file)
|
|
|
|
try:
|
|
with open(args.in_file, encoding="utf-8") as config:
|
|
xml = ET.fromstring(config.read())
|
|
except ParseError as e:
|
|
print(e)
|
|
exit(1)
|
|
|
|
# Bit of a hack here for getting parents. element.parent doesn't exist in python xml.
|
|
parents = {c:p for p in xml.iter() for c in p}
|
|
|
|
args.copy_insert = args.copy_insert.split(",")
|
|
if len(args.copy_insert) % 2 == 1:
|
|
print(f"Error: '{args.copy_insert}' is not even!")
|
|
exit(1)
|
|
# layout pairs e.g. [[copy,insert],[copy,insert]]
|
|
args.copy_insert = [args.copy_insert[f:f+2] for f in range(0, len(args.copy_insert), 2)]
|
|
# print(args.copy_insert)
|
|
for duplicate, insert in args.copy_insert:
|
|
print("========================")
|
|
print(f"Finding: {duplicate} Inserting: {insert}")
|
|
skip_insert = False
|
|
found = False
|
|
for elem in xml.iter():
|
|
if not found and elem != None and elem.text != None and duplicate.lower() in elem.text.lower():
|
|
swap = duplicate.lower()
|
|
duplicate = elem.text
|
|
insert = elem.text.lower().replace(swap, insert)
|
|
found = True
|
|
elif elem != None and elem.text != None and insert.lower() in elem.text.lower():
|
|
print(f"Error: '{insert}' already exists!")
|
|
skip_insert = True
|
|
break
|
|
|
|
if not found:
|
|
print(f"Error: Could not find '{duplicate}'")
|
|
print(f"It's not referenced in {args.in_file}")
|
|
skip_insert = True
|
|
|
|
if skip_insert:
|
|
print(f"Skipping '{insert}'")
|
|
continue
|
|
|
|
all_instances = xml.findall(f".//*[.='{duplicate}']")
|
|
|
|
print("Copying '{file}': "+duplicate)
|
|
print(f"Number: {len(all_instances)}")
|
|
print("Inserting: "+insert)
|
|
print("========================")
|
|
|
|
# Handle dataFiles (special case)
|
|
found = dataFiles.format(file=duplicate)
|
|
found = xml.find(found)
|
|
if found != None:
|
|
item = parents[found]
|
|
parent = parents[item]
|
|
dupe = copy.deepcopy(item)
|
|
dupe.find("filename").text = insert
|
|
index = list(parent).index(item)
|
|
parent.insert(index+1, dupe)
|
|
all_instances.remove(found)
|
|
# update parents, merge parent dict of dupe with parents and add parents[dupe] = parent
|
|
parents = {**parents, **{c:p for p in dupe.iter() for c in p}}
|
|
parents[dupe] = parent
|
|
elem = ET.tostring(dupe).decode().strip()
|
|
print(f"Copied {dataFiles}: \n{elem}")
|
|
print("===")
|
|
|
|
# Handle changesets
|
|
for cs_path in changeset_paths:
|
|
found = cs_path.format(file=duplicate)
|
|
found = xml.findall(found)
|
|
for f in found:
|
|
parent = parents[f]
|
|
dupe = copy.deepcopy(f)
|
|
dupe.text = insert
|
|
index = list(parent).index(f)
|
|
parent.insert(index+1, dupe)
|
|
all_instances.remove(f)
|
|
# update parents, merge parent dict of dupe with parents and add parents[dupe] = parent
|
|
parents = {**parents, **{c:p for p in dupe.iter() for c in p}}
|
|
parents[dupe] = parent
|
|
cs = parents[parent]
|
|
while cs.find("changeSetName") == None:
|
|
cs = parents[cs]
|
|
changeset = cs.find("changeSetName").text
|
|
elem = ET.tostring(dupe).decode().strip()
|
|
print(f"Copied {cs_path} '{changeset}':\n"+elem)
|
|
print("===")
|
|
|
|
if len(all_instances) != 0:
|
|
print(f"Error: not all references to '{duplicate}' handled.")
|
|
print("The script needs to be updated with the missing xpaths/instances.")
|
|
print("Element/s:")
|
|
for e in all_instances:
|
|
parent = parents[e]
|
|
elem = ET.tostring(parent).decode().strip()
|
|
print(elem)
|
|
exit(1)
|
|
print("========================\n")
|
|
|
|
if args.out_file:
|
|
ET.ElementTree(xml).write(args.out_file, encoding="utf-8", xml_declaration=True)
|
|
else:
|
|
ET.ElementTree(xml).write(args.in_file, encoding="utf-8", xml_declaration=True)
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
pass |