#!/usr/bin/env python import argparse import functools import io import sys import shutil import xmltodict from pathlib import Path def cli_parser(parameters= None): argparser = argparse.ArgumentParser(description='XML to C functions converter') argparser.add_argument('infile', type=Path, help='Input file (.xml)') argparser.add_argument('--outfile', type=Path, help='Out file (.c). Only if special filename needed.') argparser.add_argument('--dry', help='true: No outfile is generated', action='store_true') return argparser.parse_args(parameters) def trav_dict(parse_dict, prefix=''): for name, value in parse_dict.items(): function = f"{prefix}_{name}" if isinstance(value, dict): yield from trav_dict(value, prefix=function) else: yield { "funcname": function, "paramname": name, "value": value } def extract_root_section(parse_dict, name, create_setter=False): width = 80 file_stream = io.StringIO() writer = functools.partial(print, file=file_stream) header = f" {name} ".center(width, "=") writer(f"//{header}") for finding in trav_dict(parse_dict["root"][name], prefix=name): writer(f"void get_{finding['funcname']}(char* {finding['paramname']})\n" f"{{\n //{finding['value']}\n}}\n") if create_setter: writer(f"void set_{finding['funcname']}(char* {finding['paramname']})\n" f"{{\n //{finding['value']}\n}}\n") return file_stream def main(): args = cli_parser() infile = args.infile outfile = args.outfile or infile.with_suffix(".c") file_ctx = infile.read_text(encoding="UTF-8", errors="replace") xml_dict = xmltodict.parse(file_ctx) try: status_stream = extract_root_section(xml_dict, "status") config_stream = extract_root_section(xml_dict, "config", create_setter=True) except KeyError as err: print(f"Parsing XML fails seciton is missing: {err}", file=sys.stderr) sys.exit(1) if args.dry: print(status_stream.getvalue(), end='') print(config_stream.getvalue(), end='') else: with outfile.open("w", encoding="UTF-8") as outp: status_stream.seek(0) shutil.copyfileobj(status_stream, outp) config_stream.seek(0) shutil.copyfileobj(config_stream, outp) if __name__ == '__main__': main()