2010-03-10 18 views
9

Dadoelemento con el atributo con minidom

<field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 0.000008000 seconds" size="0" pos="0" show="0.000008000"/> 
<field name="frame.time_relative" showname="Time since reference or first frame: 0.000008000 seconds" size="0" pos="0" show="0.000008000"/> 
<field name="frame.number" showname="Frame Number: 2" size="0" pos="0" show="2"/> 
<field name="frame.pkt_len" showname="Packet Length: 1506 bytes" hide="yes" size="0" pos="0" show="1506"/> 
<field name="frame.len" showname="Frame Length: 1506 bytes" size="0" pos="0" show="1506"/> 
<field name="frame.cap_len" showname="Capture Length: 1506 bytes" size="0" pos="0" show="1506"/> 
<field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/> 
<field name="frame.protocols" showname="Protocols in frame: eth:ip:tcp:http:data" size="0" pos="0" show="eth:ip:tcp:http:data"/> 

¿Cómo consigo el campo con name = "frame.len" de inmediato sin iteración a través de cada etiqueta y comprobando los atributos?

+0

Para agregar a esta pregunta, el xml es de 300mb. Me quedé sin memoria la última vez que traté de analizarlo. ¿Alguna sugerencia de mejores bibliotecas de estilo de saxo? – xster

+0

Bueno, 'xml.dom.minidom' es un analizador DOM que necesita leer todo el documento en la memoria. No porque no sea lo suficientemente bueno, sino porque eso es lo que hacen los analizadores DOM. Así que no sé a qué te refieres con "mejores bibliotecas de estilo de saxo". ¿Qué tiene de malo 'xml.sax', el analizador SAX estándar que viene con Python? –

+0

Después de 5000 paquetes (300 mb), intentar cargar el xml bloquea mi computadora. De esos 300mb de datos, solo necesito unos 10kb repartidos por todo el documento. ¿Hay una manera más eficiente de atravesar el xml que lxml y una biblioteca más simple que sax? – xster

Respuesta

13

No creo que puedas.

de los padres element, es necesario

for subelement in element.GetElementsByTagName("field"): 
    if subelement.hasAttribute("frame.len"): 
     do_something() 

En respuesta a su comentario del 11 de marzo, si la estructura de sus documentos es estable y libre de sorpresas desagradables (como paréntesis angulares atributos interior), es posible que quiero probar lo impensable y usar una expresión regular. Esta no es una práctica recomendada, pero podría funcionar y ser mucho más fácil que analizar realmente el archivo. Reconozco que a veces he hecho eso. No me he quedado ciego todavía

Así, en su caso, usted podría (si se asume que una etiqueta <field> no abarca múltiples líneas):

xmlfile = open("myfile.xml") 
for line in xmlfile: 
    match = re.search(r'<field\s+name="frame.len"\s+([^>]+)/>', line): 
    if match: 
     result = match.group(1) 
     do_something(result) 

Si una etiqueta <field> puede ocupar varias líneas, podría intentar cargar el archivo completo como texto plano en la memoria y analizarlo en busca de coincidencias:

filedump = open("myfile.xml").read() 
for match in re.finditer(r'<field\s+name="frame.len"\s+([^>]+)/>', filedump): 
    result = match.group(1) 
    do_something(result) 

En ambos casos, result contendrá los atributos distintos a frame.len. La expresión regular asume que frame.len es siempre el primer atributo dentro de la etiqueta.

2

Usted no - el DOM API, algo mal diseñado (por w3c, no por Python! -) no tiene una función de búsqueda para hacer la iteración por usted. Acepte la necesidad de realizar un bucle (no a través de cada etiqueta en general, pero a través de todas con un nombre de etiqueta determinado) o actualice a una interfaz más completa, como BeautifulSoup o lxml.

0

¡Guau, esa expresión regular es horrible! A partir de 2016, existe un método .getAttribute() para cada DOMElement que hace las cosas un poco más fáciles, pero aún tiene que recorrer los elementos.

l = [] 
for e in elements: 
    if e.hasAttribute('name') and e.getAttribute('name') == 'field.len': 
     l.append(e) 
Cuestiones relacionadas