Compute the gexf representation of given power graph,
    and push it into given file.

    See https://gephi.org/gexf/format/index.html
    for format doc.

def tree_to_gexf(tree:'BubbleTree') -> str:
    """Compute the gexf representation of given power graph,
    and push it into given file.

    See https://gephi.org/gexf/format/index.html
    for format doc.

    """
    output_nodes, output_edges = '', ''

    def build_node(node:str) -> str:
        """Yield strings describing given node, recursively"""
        if tree.inclusions[node]:  # it's a powernode
            yield '<node id="{}" label="{}">'.format(node, node)
            yield '<nodes>'
            for sub in tree.inclusions[node]:
                yield from build_node(sub)
            yield '</nodes>'
            yield '</node>'
        else:  # it's a regular node
            yield '<node id="{}" label="{}"/>'.format(node, node)
        return

    # build full hierarchy from the roots
    output_nodes += '\n'.join('\n'.join(build_node(root)) for root in tree.roots)

    # # add the edges to the final graph
    for idx, (source, targets) in enumerate(tree.edges.items()):
        for target in targets:
            if source <= target:  # edges dict is complete. This avoid multiple edges.
                output_edges += '<edge id="{}" source="{}" target="{}" />\n'.format(idx, source, target)

    return GEXF_TEMPLATE.format(
        'directed' if tree.oriented else 'undirected',
        output_nodes,
        output_edges
    )