2010-09-21 16 views
0

Je dois éviter de créer des branches doubles dans une arborescence xml lors de l'analyse d'un fichier texte. Disons que le fichier texte est le suivant (l'ordre des lignes est aléatoire):Création d'une arborescence xml à partir d'un fichier texte avec Python

Branch1: branch11: message11
Branch1: branch12: message12
succursale2: branch21: message21
succursale2: branch22: message22

Donc l'arbre xml résultant devrait avoir une racine avec deux branches. Ces deux branches ont deux sous-branches. Le code Python que j'utilise pour analyser ce fichier texte est le suivant:

import string 
fh = open ('xmlbasic.txt', 'r') 
allLines = fh.readlines() 
fh.close() 
import xml.etree.ElementTree as ET 
root = ET.Element('root') 

for line in allLines: 
    tempv = line.split(':') 
    branch1 = ET.SubElement(root, tempv[0]) 
    branch2 = ET.SubElement(branch1, tempv[1]) 
    branch2.text = tempv[2] 

tree = ET.ElementTree(root) 
tree.write('xmlbasictree.xml') 

Le problème avec ce code est, qu'une branche dans l'arbre XML est créé avec chaque ligne du fichier texte.

Des suggestions pour éviter de créer une autre branche dans l'arborescence XML si une branche portant ce nom existe déjà?

Répondre

1
with open("xmlbasic.txt") as lines_file: 
    lines = lines_file.read() 

import xml.etree.ElementTree as ET 

root = ET.Element('root') 

for line in lines: 
    head, subhead, tail = line.split(":") 

    head_branch = root.find(head) 
    if not head_branch: 
     head_branch = ET.SubElement(root, head) 

    subhead_branch = head_branch.find(subhead) 
    if not subhead_branch: 
     subhead_branch = ET.SubElement(branch1, subhead) 

    subhead_branch.text = tail 

tree = ET.ElementTree(root) 
ET.dump(tree) 

La logique est simple - vous déjà dit dans votre question! Vous devez simplement vérifier si une branche existe déjà dans l'arborescence avant de la créer. Notez que cela est probablement inefficace, puisque vous recherchez jusqu'à l'arbre entier pour chaque ligne. C'est parce que ElementTree n'est pas conçu pour l'unicité.


Si vous avez besoin de vitesse (qui vous ne pouvez pas, en particulier pour les arbres assez petites!), D'une manière plus efficace serait d'utiliser un defaultdict pour stocker la structure de l'arbre avant de le convertir à un ElementTree.

import collections 
import xml.etree.ElementTree as ET 

with open("xmlbasic.txt") as lines_file: 
    lines = lines_file.read() 

root_dict = collections.defaultdict(dict) 
for line in lines: 
    head, subhead, tail = line.split(":") 
    root_dict[head][subhead] = tail 

root = ET.Element('root') 
for head, branch in root_dict.items(): 
    head_element = ET.SubElement(root, head) 
    for subhead, tail in branch.items(): 
     ET.SubElement(head_element,subhead).text = tail 

tree = ET.ElementTree(root) 
ET.dump(tree) 
+0

Merci, ceci et aussi d'autres réponses fonctionnent très bien, mais je vais m'en tenir à defaultdict comme en réalité les fichiers texte et xml être plutôt gros. – bitman

0

quelque chose le long de ces lignes? Vous conservez le niveau des branches à réutiliser dans un dict.

b1map = {} 

for line in allLines: 
    tempv = line.split(':') 
    branch1 = b1map.get(tempv[0]) 
    if branch1 is None: 
     branch1 = b1map[tempv[0]] = ET.SubElement(root, tempv[0]) 
    branch2 = ET.SubElement(branch1, tempv[1]) 
    branch2.text = tempv[2]