#!/usr/bin/env python3 """\ This script formats XML files in a given directory with options for indentation and space removal. $LicenseInfo:firstyear=2023&license=viewerlgpl$ Second Life Viewer Source Code Copyright (C) 2023, Linden Research, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2.1 of the License only. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ import os import sys import glob import io import xml.etree.ElementTree as ET def get_xml_declaration(file_path): with open(file_path, 'r', encoding='utf-8') as file: first_line = file.readline().strip() if first_line.startswith('', '/>') xml_decl = (xml_decl if (xml_decl and not rewrite_decl) else '') try: with io.open(file_path, 'wb') as file: file.write(xml_decl.encode('utf-8')) file.write('\n'.encode('utf-8')) if xml_string: file.write(xml_string.encode('utf-8')) if not xml_string.endswith('\n'): file.write('\n'.encode('utf-8')) except IOError as e: print(f"Error saving file {file_path}: {e}") def process_xml_files(file_paths, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False): found_files = False if file_paths: found_files = True for file_path in file_paths: xml_decl = get_xml_declaration(file_path) tree = parse_xml_file(file_path) if tree is not None: save_xml(tree, file_path, xml_decl, indent_text, indent_tab, rm_space, rewrite_decl) return found_files def process_directory(directory_path, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False, file_pattern=None, recursive=False): if not os.path.isdir(directory_path): print(f"Directory not found: {directory_path}") return pattern = file_pattern if file_pattern else "*.xml" found_files = False if not recursive: # Non-recursive mode xml_files = glob.glob(os.path.join(directory_path, pattern)) found_files = process_xml_files(xml_files, indent_text, indent_tab, rm_space, rewrite_decl) else: # Recursive mode for root, dirs, files in os.walk(directory_path): xml_files = glob.glob(os.path.join(root, pattern)) found_files = process_xml_files(xml_files, indent_text, indent_tab, rm_space, rewrite_decl) if not found_files: print(f"No XML files found in {'directory tree' if recursive else 'directory'}: {directory_path}") if __name__ == "__main__": if len(sys.argv) < 2 or '--help' in sys.argv: print("This script formats XML files in a given directory. Useful to fix XUI XMLs after processing by other tools.") print("\nUsage:") print(" python fix_xml_indentations.py [options]") print("\nOptions:") print(" --indent-text Indents text within XML tags.") print(" --indent-tab Uses tabs instead of spaces for indentation.") print(" --rm-space Removes spaces in self-closing tags.") print(" --rewrite_decl Replaces the XML declaration line.") print(" --file Only process files matching the pattern") print(" --recursive Process files in all subdirectories") print("\nCommon Usage:") print(" To format XML files with text indentation, tab indentation, and removal of spaces in self-closing tags:") print(" python fix_xml_indentations.py /path/to/xmls --indent-text --indent-tab --rm-space") print("\n To format specific XML files recursively through all subdirectories:") print(" python fix_xml_indentations.py /path/to/xmls --file floater_*.xml --recursive") sys.exit(1) directory_path = sys.argv[1] indent_text = '--indent-text' in sys.argv indent_tab = '--indent-tab' in sys.argv rm_space = '--rm-space' in sys.argv rewrite_decl = '--rewrite_decl' in sys.argv recursive = '--recursive' in sys.argv # Get file pattern if specified file_pattern = None if '--file' in sys.argv: try: file_index = sys.argv.index('--file') + 1 if file_index < len(sys.argv): file_pattern = sys.argv[file_index] except ValueError: pass process_directory(directory_path, indent_text, indent_tab, rm_space, rewrite_decl, file_pattern, recursive)