192 lines
5.6 KiB
Python
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>")
|