2010-03-10 20 views
9

Étant donnéTrouver élément avec l'attribut avec 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"/> 

Comment puis-je obtenir le champ avec name = « frame.len » tout de suite sans itérer toutes les balises et de vérifier les attributs?

+0

Pour ajouter à cette question, le xml est 300mb. J'ai manqué de mémoire la dernière fois que j'ai essayé de l'analyser. Des suggestions de meilleures bibliothèques de style sax? – xster

+0

Eh bien, 'xml.dom.minidom' est un parseur DOM qui a besoin de lire le document entier en mémoire. Pas parce que ce n'est pas assez bon mais parce que c'est ce que font les parseurs DOM. Donc je ne sais pas ce que vous voulez dire par "de meilleures bibliothèques de style saxophone". Qu'est-ce qui ne va pas avec 'xml.sax', l'analyseur standard SAX fourni avec Python? –

+0

Après 5000 paquets (300mb), en essayant de charger le xml bloque mon ordinateur. Sur ces 300 Mo de données, j'ai juste besoin d'environ 10 Ko dispersés dans le document. Existe-t-il un moyen plus efficace de parcourir le xml que lxml et une bibliothèque plus simple que le sax? – xster

Répondre

13

Je ne pense pas que vous le pouvez.

du parent element, vous devez

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

Réagissant à votre commentaire du 11 Mars, si la structure de vos documents est stable et sans mauvaises surprises (comme crochets attributs à l'intérieur), vous pourriez vouloir essayer l'impensable et utiliser une expression régulière. Ce n'est pas recommandé, mais cela pourrait fonctionner et être beaucoup plus facile que l'analyse du fichier. J'avoue que je l'ai fait parfois moi-même. Je ne suis pas encore devenu aveugle.

Donc, dans votre cas, vous pouvez (en supposant qu'une étiquette <field> ne couvre pas plusieurs lignes):

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 une balise <field>peut sur plusieurs lignes, vous pouvez essayer de charger le fichier entier comme le texte brut en mémoire, puis le scanner pour les matchs:

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) 

Dans les deux cas, result contiendra les attributs autres que frame.len. L'expression régulière suppose que frame.len est toujours le premier attribut à l'intérieur de la balise.

2

Vous n'avez pas - le DOM API, un peu mal conçu (par w3c, pas par Python! -) n'a pas une telle fonction de recherche pour faire l'itération pour vous. Acceptez le besoin de boucle (pas par chaque balise en général, mais à travers tous avec un nom de balise donné), ou passez à une interface plus riche, telle que BeautifulSoup ou lxml.

0

Wow, cette regex est horrible! À partir de 2016, il y a une méthode .getAttribute() pour chaque DOMElement qui rend les choses un peu plus faciles, mais vous devez encore parcourir les éléments.

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