ParamManagerScripts/backend/script_groups/XML Parser to SCL/parsers/parse_block_header.py

192 lines
5.6 KiB
Python

# 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 <xml_file>")