2010-09-21 7 views
0

Мне нужно избегать создания двойных ветвей в дереве xml при разборе текстового файла. Скажем, текстовый файл выглядит следующим образом (порядок строк является случайным):Создание дерева xml из текстового файла с помощью Python

branch1: branch11: message11
branch1: branch12: message12
branch2: branch21: message21
branch2: branch22: message22

Таким образом, полученное дерево xml должно иметь корень с двумя ветвями. Обе эти ветви имеют две дочерние части. Код Python я использую, чтобы разобрать этот текстовый файл выглядит следующим образом:

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') 

Проблема с этим кодом в том, что филиал в XML-дереве создаются с каждой строкой из текстового файла.

Любые предложения, как избежать создания другой ветки в дереве xml, если ветка с этим именем уже существует?

ответ

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) 

Логика проста - вы уже говорили это в вашем вопросе! Вам просто нужно проверить, существует ли ветвь в дереве перед ее созданием.

Обратите внимание, что это неэффективно, поскольку вы выполняете поиск по всему дереву для каждой строки. Это связано с тем, что ElementTree не предназначен для уникальности.


Если вам нужна скорость (которые вы не можете, особенно для низковат деревьев!), Более эффективным способом было бы использовать defaultdict хранить структуру дерева перед преобразованием его в 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

Спасибо, этот, а также другие ответы работают нормально, но я буду придерживаться defaultdict, поскольку на самом деле текстовые и XML-файлы будут довольно большими. – bitman

0

что-то вдоль этих линий? Вы сохраняете уровень ветвей для повторного использования в 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] 
Смежные вопросы