Как перебрать файл GraphML с помощью lxml

У меня есть следующий графический файл «mygraph.gml», который я хочу проанализировать с помощью простого скрипта python:

Это представляет собой простой граф с двумя узлами «node0», «node1» и ребро между ними

<?xml version="1.0" encoding="UTF-8"?> <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> <key id="name" for="node" attr.name="name" attr.type="string"/> <key id="weight" for="edge" attr.name="weight" attr.type="double"/> <graph id="G" edgedefault="directed"> <node id="n0"> <data key="name">node1</data> </node> <node id="n1"> <data key="name">node2</data> </node> <edge source="n1" target="n0"> <data key="weight">1</data> </edge> </graph> </graphml> 

Это представляет собой график с двумя узлами n0 и n1 с краем веса 1 между ними. Я хочу проанализировать эту структуру с помощью python.

Я написал скрипт с помощью lxml (мне нужно использовать его, потому что набор данных намного больше, чем этот простой пример, более 10 ^ 5 узлов, мини-мини-питон слишком медленный)

 import lxml.etree as et tree = et.parse('mygraph.gml') root = tree.getroot() graphml = { "graph": "{http://graphml.graphdrawing.org/xmlns}graph", "node": "{http://graphml.graphdrawing.org/xmlns}node", "edge": "{http://graphml.graphdrawing.org/xmlns}edge", "data": "{http://graphml.graphdrawing.org/xmlns}data", "label": "{http://graphml.graphdrawing.org/xmlns}data[@key='label']", "x": "{http://graphml.graphdrawing.org/xmlns}data[@key='x']", "y": "{http://graphml.graphdrawing.org/xmlns}data[@key='y']", "size": "{http://graphml.graphdrawing.org/xmlns}data[@key='size']", "r": "{http://graphml.graphdrawing.org/xmlns}data[@key='r']", "g": "{http://graphml.graphdrawing.org/xmlns}data[@key='g']", "b": "{http://graphml.graphdrawing.org/xmlns}data[@key='b']", "weight": "{http://graphml.graphdrawing.org/xmlns}data[@key='weight']", "edgeid": "{http://graphml.graphdrawing.org/xmlns}data[@key='edgeid']" } graph = tree.find(graphml.get("graph")) nodes = graph.findall(graphml.get("node")) edges = graph.findall(graphml.get("edge")) 

Этот скрипт правильно определяет узлы и ребра, чтобы я мог просто перебирать их

 for n in nodes: print n.attrib 

или аналогично по краям:

 for e in edges: print (e.attrib['source'], e.attrib['target']) 

но я не могу понять, как получить тег «data» для ребер или узлов, чтобы напечатать вес края и тег «name».

Это не работает для меня:

 weights = graph.findall(graphml.get("weight")) 

последний список всегда пуст. Зачем? Мне что-то не хватает, но я не могу понять.

    Вы не можете сделать это за один проход, но для каждого найденного узла вы можете построить dict с ключом / значением данных:

     graph = tree.find(graphml.get("graph")) nodes = graph.findall(graphml.get("node")) edges = graph.findall(graphml.get("edge")) for node in nodes + edges: attribs = {} for data in node.findall(graphml.get('data')): attribs[data.get('key')] = data.text print 'Node', node, 'have', attribs 

    Это дает результат:

     Node <Element {http://graphml.graphdrawing.org/xmlns}node at 0x7ff053d3e5a0> have {'name': 'node1'} Node <Element {http://graphml.graphdrawing.org/xmlns}node at 0x7ff053d3e5f0> have {'name': 'node2'} Node <Element {http://graphml.graphdrawing.org/xmlns}edge at 0x7ff053d3e640> have {'weight': '1'}