# ToUpload/parsers/parse_block_header.py # -*- coding: utf-8 -*- from lxml import etree import os # Importar desde las utilidades del parser from .parser_utils import ns, get_multilingual_text def parse_block_header_from_xml(xml_filepath): """ Extrae información del header del bloque desde un archivo XML de TIA Portal. Args: xml_filepath (str): Ruta al archivo XML Returns: dict: Diccionario con información del bloque: { 'block_type': 'FC' | 'FB' | 'DB' | 'UDT' | 'PlcTagTable', 'block_number': str | None, 'block_name': str | None, 'programming_language': str | None } """ if not os.path.exists(xml_filepath): return None try: tree = etree.parse(xml_filepath) root = tree.getroot() # Buscar diferentes tipos de bloques block_info = { "block_type": None, "block_number": None, "block_name": None, "programming_language": None, } # 1. Function (FC) fc_node = root.find(".//SW.Blocks.FC") if fc_node is not None: block_info["block_type"] = "FC" block_info.update(_extract_common_attributes(fc_node)) return block_info # 2. Function Block (FB) fb_node = root.find(".//SW.Blocks.FB") if fb_node is not None: block_info["block_type"] = "FB" block_info.update(_extract_common_attributes(fb_node)) return block_info # 3. Organization Block (OB) ob_node = root.find(".//SW.Blocks.OB") if ob_node is not None: block_info["block_type"] = "OB" block_info.update(_extract_common_attributes(ob_node)) return block_info # 4. Data Block (DB) - Global db_node = root.find(".//SW.Blocks.GlobalDB") if db_node is not None: block_info["block_type"] = "GlobalDB" block_info.update(_extract_common_attributes(db_node)) return block_info # 5. Data Block (DB) - Instance idb_node = root.find(".//SW.Blocks.InstanceDB") if idb_node is not None: block_info["block_type"] = "InstanceDB" block_info.update(_extract_common_attributes(idb_node)) return block_info # 6. User Defined Type (UDT) udt_node = root.find(".//SW.Types.PlcStruct") if udt_node is not None: block_info["block_type"] = "PlcUDT" block_info.update(_extract_common_attributes(udt_node)) return block_info # 7. Tag Table tag_table_node = root.find(".//SW.Tags.PlcTagTable") if tag_table_node is not None: block_info["block_type"] = "PlcTagTable" block_info.update(_extract_common_attributes(tag_table_node)) return block_info return None except Exception as e: print(f"Error parsing block header from {xml_filepath}: {e}") return None def _extract_common_attributes(block_node): """ Extrae atributos comunes de un nodo de bloque. Args: block_node: Nodo XML del bloque Returns: dict: Diccionario con atributos extraídos """ attributes = {} # Buscar AttributeList attr_list = block_node.find("AttributeList") if attr_list is not None: # Nombre del bloque name_elem = attr_list.find("Name") if name_elem is not None: attributes["block_name"] = name_elem.text # Número del bloque number_elem = attr_list.find("Number") if number_elem is not None: attributes["block_number"] = str(number_elem.text) # Lenguaje de programación lang_elem = attr_list.find("ProgrammingLanguage") if lang_elem is not None: attributes["programming_language"] = lang_elem.text return attributes def generate_block_header_comment(block_info): """ Genera el comentario de header del bloque basado en la información extraída. Args: block_info (dict): Información del bloque extraída del XML Returns: str: Línea de comentario del header (ej: "// FC1032") """ if not block_info or not block_info.get("block_type"): return None block_type = block_info["block_type"] block_number = block_info.get("block_number") # Mapear tipos de bloque a abreviaciones type_mapping = { "FC": "FC", "FB": "FB", "OB": "OB", "GlobalDB": "DB", "InstanceDB": "DB", "PlcUDT": "UDT", "PlcTagTable": "TAG", } abbreviated_type = type_mapping.get(block_type, block_type) if block_number: return f"// {abbreviated_type}{block_number}" else: return f"// {abbreviated_type}" # Función de conveniencia para uso directo def get_block_header_comment_from_xml(xml_filepath): """ Función de conveniencia que extrae la información del bloque y genera el comentario de header. Args: xml_filepath (str): Ruta al archivo XML Returns: str | None: Comentario de header (ej: "// FC1032") o None si no se pudo extraer """ block_info = parse_block_header_from_xml(xml_filepath) if block_info: return generate_block_header_comment(block_info) return None if __name__ == "__main__": # Ejemplo de uso para testing import sys if len(sys.argv) > 1: xml_file = sys.argv[1] header = get_block_header_comment_from_xml(xml_file) print(f"Header for {xml_file}: {header}") else: print("Usage: python parse_block_header.py ")