from lxml import etree class Xml_reader: """ reader for the XML configuration """ def __init__(self, xml_path: str, xsd_path: str): """inits the reader Args: xml_path (str): the path to the XML file xsd_path (str): the path to the XSD file Raises: SyntaxError: validity of XML file is checked with the XSD file """ #check the XML for validity using the XSD file if not self.validate(xml_path,xsd_path): raise SyntaxError('the XML config file has an invalid syntax') self.set_root(xml_path) def set_root(self, xml_path: str): self.root = etree.parse(xml_path).getroot() def validate(self, xml_path: str, xsd_path: str) -> bool: """validates a XML by using a XSD file Args: xml_path (str): the path to the XML file xsd_path (str): the path to the XSD file Returns: bool: result of the validation """ xml_schema = etree.XMLSchema(etree.parse(xsd_path)) return xml_schema.validate(etree.parse(xml_path)) def get_device_names(self) -> list: """lists all the device names from the config XML Returns: list: all device names as strings """ return [device.get("name") for device in self.root.findall('Device')] def get_value_info(self,device_name: str) -> dict: """returns the value information for a given device Args: device_name (str): the name of a device Returns: dict: {'type','unit','offset','factor'} Raises: NameError: device_name will be checked against the config XML """ #check if a device exists in the config XML if self.root.find("Device[@name='%s']" % device_name) is None: raise NameError("unknown device %s" % device_name) value_info = self.root.find( "Device[@name='%s']/ValueInfo" % device_name) #format the output return { 'type': value_info.get('type'), 'unit': value_info.get('unit'), 'offset': None if value_info.find("Offset") is None else value_info.find("Offset").text, 'factor': None if value_info.find("Factor") is None else value_info.find("Factor").text, } def get_port(self,device_name:str) -> dict: """returns the information about a port of a given device Args: device_name (str): the name of a device Returns: dict: {'protocol', [list: pins]} Raises: NameError: device_name will be checked against the config XML """ if self.root.find("Device[@name='%s']" % device_name) is None: raise NameError("unknown device %s" % device_name) port = self.root.find( "Device[@name='%s']/Port" % device_name) return { 'protocol': port.get('protocol'), 'pins': [ pin.text for pin in self.root.findall( "Device[@name='%s']/Port/Pin" % device_name ) ] } # ##test # xml_reader = Xml_reader('XML/Test.xml','XML/config.xsd') # print(xml_reader.get_device_names) # print(xml_reader.get_value_info("example")) # print(xml_reader.get_port("example")) # print(xml_reader.get_value_info("sensorarray")) # print(xml_reader.get_port("sensorarray"))