#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Script de debugging para entender por qué los índices de array simples como [#i] no funcionan """ import os import sys from lxml import etree # Agregar el directorio del script al path script_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(script_dir) from parsers.parse_scl import reconstruct_scl_from_tokens from parsers.parser_utils import ns def debug_array_parsing(): """Función para debug del parsing de arrays""" # Cargar el archivo XML problemático xml_path = r"D:\Trabajo\VM\45 - HENKEL - VM Auto Changeover\ExportTia\PLC_TL27_Q1\ProgramBlocks_XML\FB HMI Interlock.xml" print(f"Cargando XML: {xml_path}") # Cargar y parsear el XML with open(xml_path, "r", encoding="utf-8") as f: content = f.read() root = etree.fromstring(content) # Buscar todas las instancias de i_Request print("\n=== Buscando todas las instancias de i_Request ===") # Buscar elementos Component con Name="i_Request" components = root.xpath("//Component[@Name='i_Request']") print(f"Encontrados {len(components)} componentes i_Request") # Si no encontramos nada, buscar de manera más amplia if len(components) == 0: print("No se encontraron con XPath directo, buscando de manera recursiva...") components = [] for elem in root.iter(): if elem.tag.endswith("Component") and elem.get("Name") == "i_Request": components.append(elem) print( f"Encontrados {len(components)} componentes i_Request con búsqueda recursiva" ) for i, comp in enumerate(components): print(f"\n--- Componente {i+1} (UId={comp.get('UId')}) ---") # Obtener todos los hijos children = comp.xpath("./*") print(f"Número de hijos: {len(children)}") for j, child in enumerate(children): tag = etree.QName(child.tag).localname print(f" Hijo {j}: {tag}") if tag == "Token": print(f" Text: '{child.get('Text')}'") elif tag == "Access": print(f" Scope: '{child.get('Scope')}'") # Buscar Symbol dentro del Access symbols = child.xpath(".//Symbol") if symbols: symbol_components = symbols[0].xpath(".//Component") for sc in symbol_components: print(f" Component: '{sc.get('Name')}'") # Verificar si este componente tiene patrón de array has_array_pattern = False bracket_start_idx = -1 bracket_end_idx = -1 # Buscar los tokens [ y ] for idx, child in enumerate(children): tag = etree.QName(child.tag).localname if tag == "Token": text = child.get("Text") if text == "[" and bracket_start_idx == -1: bracket_start_idx = idx elif text == "]" and bracket_start_idx != -1: bracket_end_idx = idx break if bracket_start_idx != -1 and bracket_end_idx != -1: has_array_pattern = True print( f" Corchetes encontrados en índices: {bracket_start_idx} y {bracket_end_idx}" ) print(f" Tiene patrón de array: {has_array_pattern}") if has_array_pattern: print(" >>> Este componente debería ser procesado como array <<<") # Simular el procesamiento manual del Access del medio for middle_idx in range(bracket_start_idx + 1, bracket_end_idx): middle_child = children[middle_idx] child_tag = etree.QName(middle_child.tag).localname print(f" Procesando elemento medio {middle_idx}: {child_tag}") if child_tag == "Access": scope = middle_child.get("Scope") print(f" Scope: {scope}") if scope == "LocalVariable": print(" >>> Es LocalVariable, procesando manualmente <<<") # Debug: mostrar toda la estructura del Access print(" Estructura completa del Access:") def print_xml_structure(elem, indent=" "): tag = etree.QName(elem.tag).localname attrs = dict(elem.attrib) print(f"{indent}{tag}: {attrs}") for child in elem: print_xml_structure(child, indent + " ") print_xml_structure(middle_child) # Buscar Symbol con diferentes métodos symbol_elem_ns = middle_child.xpath( "./st:Symbol", namespaces=ns ) symbol_elem_no_ns = middle_child.xpath("./Symbol") symbol_elem_recursive = [] for child in middle_child: if etree.QName(child.tag).localname == "Symbol": symbol_elem_recursive.append(child) print(f" Symbol con namespace: {len(symbol_elem_ns)}") print(f" Symbol sin namespace: {len(symbol_elem_no_ns)}") print( f" Symbol recursivo manual: {len(symbol_elem_recursive)}" ) # Usar el método que funcione symbol_elem = None if symbol_elem_ns: symbol_elem = symbol_elem_ns print(" Usando Symbol con namespace") elif symbol_elem_no_ns: symbol_elem = symbol_elem_no_ns print(" Usando Symbol sin namespace") elif symbol_elem_recursive: symbol_elem = symbol_elem_recursive print(" Usando Symbol recursivo manual") if symbol_elem: print( f" Procesando Symbol (total: {len(symbol_elem)})" ) # Buscar componentes dentro del Symbol components_inner_ns = symbol_elem[0].xpath( "./st:Component", namespaces=ns ) components_inner_no_ns = symbol_elem[0].xpath("./Component") components_inner_manual = [] for child in symbol_elem[0]: if etree.QName(child.tag).localname == "Component": components_inner_manual.append(child) print( f" Componentes con namespace: {len(components_inner_ns)}" ) print( f" Componentes sin namespace: {len(components_inner_no_ns)}" ) print( f" Componentes manual: {len(components_inner_manual)}" ) # Usar el método que funcione components_inner = None if components_inner_ns: components_inner = components_inner_ns print(" Usando componentes con namespace") elif components_inner_no_ns: components_inner = components_inner_no_ns print(" Usando componentes sin namespace") elif components_inner_manual: components_inner = components_inner_manual print(" Usando componentes manual") if components_inner: print( f" Componentes internos encontrados: {len(components_inner)}" ) result_parts = [] for k, comp_inner in enumerate(components_inner): name = comp_inner.get("Name", "_ERR_COMP_") print(f" Componente {k}: '{name}'") if k == 0: result_parts.append(f"#{name}") print(f" -> Se convertirá en: #{name}") else: result_parts.append(f".{name}") print(f" -> Se convertirá en: .{name}") final_result = "".join(result_parts) print( f" >>> RESULTADO FINAL: '{final_result}' <<<" ) else: print(" ERROR: No se encontraron componentes") else: print( " ERROR: No se encontró Symbol dentro del Access" ) print("\n=== Fin del análisis ===") if __name__ == "__main__": debug_array_parsing()