Add xml and json parsers
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
import click
|
||||
|
||||
def _get_fields(json_data: dict) -> list[str]:
|
||||
"""
|
||||
Extract field names from a JSON data structure.
|
||||
|
||||
Args:
|
||||
json_data (dict): The JSON data from which to extract field names.
|
||||
|
||||
Returns:
|
||||
list[str]: A list of field names extracted from the JSON data.
|
||||
"""
|
||||
attributes = json_data["conceptCodes"][0]["attributes"]
|
||||
namelist = [attribute["attributeName"] for attribute in attributes]
|
||||
return namelist
|
||||
|
||||
def parse_json(json_file: Path) -> list[str]:
|
||||
"""
|
||||
Parse a JSON file and extract field names.
|
||||
|
||||
Args:
|
||||
json_file (Path): The path to the JSON file to parse.
|
||||
|
||||
Returns:
|
||||
list[str]: A list of field names extracted from the JSON file.
|
||||
|
||||
Raises:
|
||||
click.FileError: If the file is not a valid JSON file.
|
||||
"""
|
||||
try:
|
||||
with open(json_file, "r") as f:
|
||||
json_data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
raise click.FileError(json_file, "Not a valid JSON file.")
|
||||
return _get_fields(json_data)
|
||||
@@ -0,0 +1,121 @@
|
||||
import lxml.etree as ET
|
||||
from pathlib import Path
|
||||
import click
|
||||
|
||||
def write_xml_data(root: ET.Element, file_path: Path, pretty: bool = True) -> None:
|
||||
if file_path.exists():
|
||||
file_path.rename(file_path.with_suffix(".bak"))
|
||||
xml_str = ET.tostring(root, encoding="utf-8", xml_declaration=True, pretty_print=pretty)
|
||||
if pretty:
|
||||
# Parse the XML string to ensure proper indentation
|
||||
parser = ET.XMLParser(remove_blank_text=True, strip_cdata=False)
|
||||
root = ET.fromstring(xml_str, parser=parser)
|
||||
xml_str = ET.tostring(root, encoding="utf-8", xml_declaration=True, pretty_print=pretty)
|
||||
file_path.write_bytes(xml_str)
|
||||
|
||||
def _sanitize_name(name: str) -> str:
|
||||
"""
|
||||
Sanitize a name by removing all non-letter characters except hyphens and Scandinavian letters.
|
||||
"""
|
||||
# Replace Scandinavian letters
|
||||
name = name.replace('ä', 'a').replace('ö', 'o')
|
||||
name = name.replace('Ä', 'A').replace('Ö', 'O')
|
||||
# Remove all non-letter characters except hyphens
|
||||
return ''.join(c for c in name if c.isalpha() or c == '-')
|
||||
|
||||
def add_connection(root: ET.Element, name: str, attr_list: list[str], description: str = "Default description") -> ET.Element:
|
||||
"""
|
||||
Add a new connection parameter to the XML configuration.
|
||||
|
||||
Args:
|
||||
root (ET.Element): The root element of the XML configuration.
|
||||
name (str): The name of the connection parameter.
|
||||
description (str, optional): The description of the connection parameter. Defaults to "Default description".
|
||||
|
||||
Returns:
|
||||
ET.Element: The modified root element with the new connection parameter added.
|
||||
"""
|
||||
connection_parameters = root.find("ConnectionParameters")
|
||||
if connection_parameters is None:
|
||||
connection_parameters = ET.SubElement(root, "ConnectionParameters")
|
||||
ET.SubElement(connection_parameters, "ConnectionParameter", Name=f"VarhaUrl{name}", Description=f"Codeserver url for {description}")
|
||||
|
||||
initialization = root.find("Initialization")
|
||||
if initialization is not None:
|
||||
predefined_commands = initialization.find("PredefinedCommands")
|
||||
if predefined_commands is None:
|
||||
predefined_commands = ET.SubElement(initialization, "PredefinedCommands")
|
||||
ET.SubElement(predefined_commands, "Command", Name=f"Get-AllCodeServerPages{name}", Description=f"Get all pages for {name}")
|
||||
ET.SubElement(predefined_commands, "Command", Name=f"Get-CodeServerPage{name}", Description=f"Get a specific page for {name}")
|
||||
|
||||
schema = root.find("Schema")
|
||||
if schema is not None:
|
||||
|
||||
new_class = ET.SubElement(schema, "Class", Name=f"CodeServerObject{name}")
|
||||
properties = ET.SubElement(new_class, "Properties")
|
||||
property = ET.SubElement(properties, "Property", Name="conceptCodeId", DataType="String", IsMultivalue="false", IsAutoFill="false", IsUniqueKey="true")
|
||||
return_binding = ET.SubElement(property, "ReturnBinding")
|
||||
ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-AllCodeServerPages{name}", Path="conceptCodeId")
|
||||
ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-CodeServerPage{name}", Path="conceptCodeId")
|
||||
mapping = ET.SubElement(property, "CommandMappings")
|
||||
ET.SubElement(mapping, "Map", ToCommand=f"Get-CodeServerPages{name}", Parameter="conceptCodeId")
|
||||
|
||||
for attr in attr_list:
|
||||
property = ET.SubElement(properties, "Property", Name=_sanitize_name(attr), DataType="String", IsMultivalue="false", IsAutoFill="false")
|
||||
return_binding = ET.SubElement(property, "ReturnBinding")
|
||||
ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-AllCodeServerPages{name}", Path=_sanitize_name(attr))
|
||||
ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-CodeServerPage{name}", Path=_sanitize_name(attr))
|
||||
|
||||
read_configuration = ET.SubElement(new_class, "ReadConfiguration")
|
||||
listing_command = ET.SubElement(read_configuration, "ListingCommand", Command=f"Get-AllCodeServerPages{name}")
|
||||
ET.SubElement(listing_command, "SetParameter", Param="Resource", Source="ConnectionParameter", Value=f"VarhaUrl{name}")
|
||||
ET.SubElement(listing_command, "SetParameter", Param="RootProperty", Source="FixedValue", Value="conceptCodes")
|
||||
cmd_squence = ET.SubElement(read_configuration, "CommandSequence")
|
||||
item = ET.SubElement(cmd_squence, "Item", Command=f"Get-CodeServerPage{name}", Order="1")
|
||||
ET.SubElement(item, "SetParameter", Param="Resource", Source="ConnectionParameter", Value=f"VarhaUrl{name}")
|
||||
ET.SubElement(item, "SetParameter", Param="RootProperty", Source="FixedValue", Value="conceptCodes")
|
||||
return root
|
||||
|
||||
def _generate_xml_configuration() -> ET.Element:
|
||||
"""
|
||||
Generate a default XML configuration for a PowerShell connector.
|
||||
|
||||
Returns:
|
||||
ET.Element: The root element of the XML configuration.
|
||||
"""
|
||||
root = ET.Element("PowershellConnectorDefinition", Id="CodeServerConnector", Version="0.1", Description="CodeServer REST api connector")
|
||||
ET.SubElement(root, "PluginAssemblies")
|
||||
ET.SubElement(root, "ConnectionParameters")
|
||||
initialization = ET.SubElement(root, "Initialization")
|
||||
ET.SubElement(initialization, "PredefinedCommands")
|
||||
custom_commands = ET.SubElement(initialization, "CustomCommands")
|
||||
cmd = ET.SubElement(custom_commands, "CustomCommand", Name="Initialize-CodeServer")
|
||||
cmd.text = ET.CDATA(r"""param (
|
||||
)
|
||||
Import-Module D:\bin\VSHVA\PowerShell\CodeServerConnector.psm1""")
|
||||
environment_initialization = ET.SubElement(initialization, "EnvironmentInitialization")
|
||||
connect = ET.SubElement(environment_initialization, "Connect")
|
||||
command_sequence = ET.SubElement(connect, "CommandSequence")
|
||||
ET.SubElement(command_sequence, "Item", Command="Initialize-CodeServer", Order="1")
|
||||
ET.SubElement(environment_initialization, "Disconnect")
|
||||
ET.SubElement(root, "Schema")
|
||||
return root
|
||||
|
||||
def get_xml_data(xml_file: Path) -> ET.Element:
|
||||
"""
|
||||
Get XML data from a file. If the file does not exist, generate a default configuration.
|
||||
|
||||
Args:
|
||||
xml_file (Path): The path to the XML file.
|
||||
|
||||
Returns:
|
||||
ET.Element: The root element of the XML configuration.
|
||||
"""
|
||||
if not xml_file.exists():
|
||||
return _generate_xml_configuration()
|
||||
try:
|
||||
parser = ET.XMLParser(strip_cdata=False)
|
||||
tree = ET.parse(xml_file, parser=parser)
|
||||
return tree
|
||||
except ET.XMLSyntaxError as e:
|
||||
raise click.FileError(xml_file, f"Not a valid XML file. {e}")
|
||||
Reference in New Issue
Block a user