Topic: Point to point wire/cable list generator

This python script takes a qet project file and produces a point to point wiring list as a CSV file. It includes Foilo referencing of coming and going arrows but it will not work well with crosses, splices and other wire joins which were not of interest to my end use case anyway

An example of the CSV loaded in to excel is provided.

The propose was to provide a list of wires for wiring a machine/panel so the correct size an color of wire can be selected and correctly labeled and it is very obvious which terminals it connects to

and thus the list contains,

Start location, part, designator, terminal ID
End location, part designator, terminal ID
conductor_section, conductor_function, conductor color, and conductor number

Clearly the more you fill in for conductor details, and if you edit the symbols to actually use the terminal names you will get more out but it works for my purpose and may be it is of use to others?


import zipfile
import xml.etree.ElementTree as ET
import os
import tempfile
import csv

def extract_content_qet(file_path):
    """Unzip .qetz or return .qet path"""
    if zipfile.is_zipfile(file_path):
        with zipfile.ZipFile(file_path, 'r') as zip_ref:
            temp_dir = tempfile.mkdtemp()
            zip_ref.extract('content.qet', temp_dir)
            return os.path.join(temp_dir, 'content.qet')
    return file_path

def build_terminal_uuid_map(root):
    """Builds a dict mapping terminal UUIDs to their names"""
    terminal_map = {}
    for terminal in root.iter('terminal'):
        uuid = terminal.get('uuid')
        name = terminal.get('name')
        if uuid and name:
            terminal_map[uuid] = name
    return terminal_map

def build_link_uuid_map(root):
    """Builds a dict mapping link UUIDs to their associated element UUIDs"""
    link_map = {}

    for element in root.iter('element'):
        element_uuid = element.get('uuid')
        links_node = element.find('links_uuids')
        if links_node is not None:
            for link in links_node.findall('link_uuid'):
                link_uuid = link.get('uuid')
                if link_uuid:
                    print(f"{element_uuid} -> {link_uuid}")
                    link_map[link_uuid] = element_uuid  # You can also store the full element if needed
    return link_map


def find_element_by_uuid(root, target_uuid):
    """Finds the <element> with the given UUID"""
    for element in root.iter('element'):
        if element.get('uuid') == target_uuid:
            return element
    return None


def find_parent_by_uuid(root, target_uuid):
    """Finds the parent of the <element> with the given UUID"""
    for parent in root.iter('diagram'):
        
        for child in parent.iter('element'):
            if child.get("uuid") == target_uuid:
                return parent
    return None

def extract_conductors_with_terminal_names(root, terminal_map,link_map):
    """Extracts conductor data and resolves terminal UUIDs to names"""
    conductors = []

    seenlinks = []
    
    for conductor in root.iter('conductor'):
        start_uuid = conductor.get('terminal1')
        end_uuid = conductor.get('terminal2')


        element1_name = conductor.get('element1_name')
        element1_label = conductor.get('element1_label')
        element1_uuid =conductor.get('element1')
        
        element2_name = conductor.get('element2_name')
        element2_label = conductor.get('element2_label')
        element2_uuid =conductor.get('element2')

        seen = False

        
        if(conductor.get('element1_name') == "Going arrow" or conductor.get('element1_name') == "Coming arrow"):
            element1_name = "*****";
            print("Element 1 is a reference")
            print(f"Element 1 uuid = {element1_uuid}")
            ele = find_element_by_uuid(root,element1_uuid )
            if ele is not None:
                links_node = ele.find('links_uuids')
                if links_node is not None:
                    for link in links_node.findall('link_uuid'):
                        link_uuid = link.get('uuid')
                        if link_uuid:

                            if link_uuid in seenlinks:
                                print(f"link uuuid {link_uuid} already seen")
                                seen=True
                            else:
                                print(f"Element 1 link uuuid {link_uuid}")
                                for conductor2 in root.iter('conductor'):
                                    if conductor2.get('element2') == link_uuid:
                                        print(f"adding {element1_uuid}")
                                        seenlinks.append(element1_uuid)
                                        element1_name = conductor2.get('element1_name')
                                        element1_label = conductor2.get('element1_label')
                                        element1_uuid = conductor2.get('element1')
                                        start_uuid = conductor2.get('terminal1')
                                    if conductor2.get('element1') == link_uuid:
                                        print(f"adding {element2_uuid}")
                                        seenlinks.append(element2_uuid)
                                        element1_name = conductor2.get('element2_name')
                                        element1_label = conductor2.get('element2_label')
                                        element1_uuid = conductor2.get('element2')
                                        start_uuid = conductor2.get('terminal2')
                                      
             
        if(conductor.get('element2_name') == "Going arrow" or conductor.get('element2_name') == "Coming arrow"):
            print("Element 2 is a reference")
            print(f"Element 2 uuid = {element2_uuid}")
            ele = find_element_by_uuid(root,element2_uuid )
            if ele is not None:
                links_node = ele.find('links_uuids')
                if links_node is not None:
                    for link in links_node.findall('link_uuid'):
                        link_uuid = link.get('uuid')
                        if link_uuid:
                            if link_uuid in seenlinks:
                                print(f"link uuuid {link_uuid} already seen")
                                seen=True
                            else: 
                                print(f"Element 2 link uuuid {link_uuid}")
                                for conductor2 in root.iter('conductor'):
                                    if conductor2.get('element1') == link_uuid:
                                        print(f"adding {element2_uuid}")
                                        seenlinks.append(element2_uuid)
                                        element2_name = conductor2.get('element2_name')
                                        element2_label = conductor2.get('element2_label')
                                        element2_uuid = conductor2.get('element2')
                                        end_uuid = conductor2.get('terminal2')
                                    if conductor2.get('element2') == link_uuid:
                                        print(f"adding {element1_uuid}")
                                        seenlinks.append(element1_uuid)
                                        element2_name = conductor2.get('element1_name')
                                        element2_label = conductor2.get('element1_label')
                                        element2_uuid = conductor2.get('element1')
                                        end_uuid = conductor2.get('terminal1')
                                       
            

        ele1 = find_element_by_uuid(root,element1_uuid )
        ele2 = find_element_by_uuid(root,element2_uuid )

        element1_loc = ""
        element2_loc = ""
        
        info_container = ele1.find('elementInformations')
        if info_container is not None:
            for elem in info_container.findall('elementInformation'):
                if elem.attrib.get('name') == 'location':
                    element1_loc = elem.text

        info_container = ele2.find('elementInformations')
        if info_container is not None:
            for elem in info_container.findall('elementInformation'):
                if elem.attrib.get('name') == 'location':
                    element2_loc = elem.text

        
        if seen == False :


            if not element1_loc:
                print(f"Element1 loc is empty")
                parent = find_parent_by_uuid(root,element1_uuid)
                if parent:
                    element1_loc = "+"+parent.get('locmach')

            if not element2_loc:
                print(f"Element2 loc is empty")
                parent = find_parent_by_uuid(root,element2_uuid)
                if parent:
                    element2_loc = "+"+parent.get('locmach')
                
                
            conductors.append({
                'S LOC': element1_loc,
                'S PART': element1_name,
                'S DESIGNATOR': element1_label,
                'S TERMINAL': terminal_map.get(start_uuid),
                'E LOC': element2_loc,
                'E PART': element2_name,
                'E DESIGNATOR': element2_label,
                'E TERMINAL': terminal_map.get(end_uuid),
                'Conductor Section': conductor.get('conductor_section'),
                'Conductor Function': conductor.get('function'),
                'Color': conductor.get('conductor_color'),
                'Designator': conductor.get('num')
        })
    return conductors

def process_qet_file(file_path, output_csv='conductors_named.csv'):
    qet_path = extract_content_qet(file_path)
    tree = ET.parse(qet_path)
    root = tree.getroot()

    terminal_map = build_terminal_uuid_map(root)
    link_map = build_link_uuid_map(root)
    conductors = extract_conductors_with_terminal_names(root, terminal_map,link_map)

    # Output to CSV
    if conductors:
        with open(output_csv, 'w', newline='') as f:
            writer = csv.DictWriter(f, fieldnames=conductors[0].keys())
            writer.writeheader()
            writer.writerows(conductors)
        print(f"Exported {len(conductors)} conductors to {output_csv}")
    else:
        print("No conductors found.")

# Example usage
if __name__ == "__main__":
    process_qet_file("c:\\yourfile.qet")
        

Post's attachments

Attachment icon example.jpg 283.92 kb, 2 downloads since 2025-09-02 

Re: Point to point wire/cable list generator

Hi Robin,
many thanks for your contribution and for sharing your python script. nomicons/wink

Related to xmlstarlet workaround:
https://qelectrotech.org/forum/viewtopi … 030#p20030

"Le jour où tu découvres le Libre, tu sais que tu ne pourras jamais plus revenir en arrière..."Questions regarding QET belong in this forum and will NOT be answered via PM! – Les questions concernant QET doivent être posées sur ce forum et ne seront pas traitées par MP !