سؤال

أحتاج إلى تجنب إنشاء فروع مزدوجة في شجرة XML عند تحليل ملف نصي. دعنا نقول أن textfile كما يلي (ترتيب الخطوط عشوائي):

الفرع 1: فرع 11: رسالة 11
الفرع 1: الفرع 12: 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 مع كل سطر من TextFile.

أي اقتراحات كيفية تجنب إنشاء فرع آخر في شجرة XML في حالة وجود فرع بهذا الاسم بالفعل؟

هل كانت مفيدة؟

المحلول

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)

نصائح أخرى

شيء على طول هذه الخطوط؟ أنت تحافظ على مستوى الفروع المراد إعادة استخدامها في القولان.

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]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top