2008-09-24 13 views
8

मैं पाइथन में टेम्पलेट xml फ़ाइल से अनुकूलित xml फ़ाइलों को उत्पन्न करने का प्रयास कर रहा हूं।पायथन में एक शब्दकोश के रूप में एक्सएमएल संपादन?

संकल्पनात्मक रूप से, मैं टेम्पलेट xml में पढ़ना चाहता हूं, कुछ तत्वों को हटा सकता हूं, कुछ टेक्स्ट विशेषताओं को बदल सकता हूं, और फ़ाइल में नया एक्सएमएल लिख सकता हूं। मैं यह कुछ इस तरह काम करना चाहता था:

conf_base = ConvertXmlToDict('config-template.xml') 
conf_base_dict = conf_base.UnWrap() 
del conf_base_dict['root-name']['level1-name']['leaf1'] 
del conf_base_dict['root-name']['level1-name']['leaf2'] 

conf_new = ConvertDictToXml(conf_base_dict) 

अब मैं फाइल करने के लिए लिखना चाहते हैं, लेकिन मैं ElementTree.ElementTree.write()

conf_new.write('config-new.xml') 

है पर पहुंचने का तरीका नहीं दिख रहा है ऐसा करने का कोई तरीका है, या कोई इसे अलग तरीके से करने का सुझाव दे सकता है?

उत्तर

8

अजगर में XML का आसान हेरफेर के लिए, मैं Beautiful Soup पुस्तकालय की तरह।

नमूना XML फ़ाइल::

<root> 
    <level1>leaf1</level1> 
    <level2>leaf2</level2> 
</root> 

अजगर कोड:

from BeautifulSoup import BeautifulStoneSoup, Tag, NavigableString 

soup = BeautifulStoneSoup('config-template.xml') # get the parser for the xml file 
soup.contents[0].name 
# u'root' 

आप तरीके के रूप में नोड नाम का उपयोग कर सकते हैं: यह कुछ इस तरह काम करता है

soup.root.contents[0].name 
# u'level1' 

यह भी है Regexes का उपयोग करने के लिए संभव:

import re 
tags_starting_with_level = soup.findAll(re.compile('^level')) 
for tag in tags_starting_with_level: print tag.name 
# level1 
# level2 

जोड़ा जा रहा है और नए नोड्स डालने बिल्कुल स्पष्ट है:

# build and insert a new level with a new leaf 
level3 = Tag(soup, 'level3') 
level3.insert(0, NavigableString('leaf3') 
soup.root.insert(2, level3) 

print soup.prettify() 
# <root> 
# <level1> 
# leaf1 
# </level1> 
# <level2> 
# leaf2 
# </level2> 
# <level3> 
# leaf3 
# </level3> 
# </root> 
+3

सुंदर सूप सबकुछ कम मामले में बदल देता है। वह वास्तव में बेकार है। मुझे टैग और मूल्यों के मामलों को संरक्षित करना है! – user236215

+0

सुंदर सूप के लेखक कहते हैं कि ऐसा इसलिए है क्योंकि HTMLParser इसे करता है। "अगर आपको टैग केस को संरक्षित करने की आवश्यकता है, तो lxml आज़माएं"। – nealmcb

11

मुझे यकीन नहीं है कि जानकारी सेट को नेस्टेड डिकट्स में कनवर्ट करना सबसे आसान है। ElementTree का उपयोग करना, आप यह कर सकते हैं:

import xml.etree.ElementTree as ET 
doc = ET.parse("template.xml") 
lvl1 = doc.findall("level1-name")[0] 
lvl1.remove(lvl1.find("leaf1") 
lvl1.remove(lvl1.find("leaf2") 
# or use del lvl1[idx] 
doc.write("config-new.xml") 

ElementTree, ताकि आप सूची में अपने XML पेड़ कन्वर्ट करने के लिए नहीं है और पहले विशेषताओं का डिजाइन किया गया था यह वास्तव में है कि आंतरिक रूप से उपयोग करता है के बाद से।

यह XPath के छोटे सबसेट के रूप में भी समर्थन करता है।

+1

रूप में अच्छी तरह सिर्फ '' find' lvl1' काम पर उपयोग कर सकते हैं, बजाय 'findall' और पहला तत्व प्राप्त करना। –

0

क्या आपने यह कोशिश की है?

print xml.etree.ElementTree.tostring(conf_new) 
19

यह आपको एक dict मिल शून्य से जिम्मेदार बताते करेंगे ... पता है कि अगर यह किसी के लिए उपयोगी है। जब मैं इसके साथ आया तो मैं खुद को समाधान देने के लिए एक एक्सएमएल की तलाश में था।



import xml.etree.ElementTree as etree 

tree = etree.parse('test.xml') 
root = tree.getroot() 

def xml_to_dict(el): 
    d={} 
    if el.text: 
    d[el.tag] = el.text 
    else: 
    d[el.tag] = {} 
    children = el.getchildren() 
    if children: 
    d[el.tag] = map(xml_to_dict, children) 
    return d 

यह: http://www.w3schools.com/XML/note.xml

<note> 
<to>Tove</to> 
<from>Jani</from> 
<heading>Reminder</heading> 
<body>Don't forget me this weekend!</body> 
</note> 

इस के बराबर हैं:


{'note': [{'to': 'Tove'}, 
      {'from': 'Jani'}, 
      {'heading': 'Reminder'}, 
      {'body': "Don't forget me this weekend!"}]} 
+0

मेरे लिए बहुत उपयोगी है; धन्यवाद! – mellort

+0

यह वही था जो मैं खोज रहा था। और 'मैप' का उपयोग मेरे लिए बोनस अंक प्राप्त करता है। बहुत बढ़िया। –

0

सबसे सीधा तरीका मेरे लिए:

root  = ET.parse(xh) 
data  = root.getroot() 
xdic  = {} 
if data > None: 
    for part in data.getchildren(): 
     xdic[part.tag] = part.text 
4

डैनियल जवाब का मेरे संशोधन, एक देने के लिए marginall y neater शब्दकोश:

def xml_to_dictionary(element): 
    l = len(namespace) 
    dictionary={} 
    tag = element.tag[l:] 
    if element.text: 
     if (element.text == ' '): 
      dictionary[tag] = {} 
     else: 
      dictionary[tag] = element.text 
    children = element.getchildren() 
    if children: 
     subdictionary = {} 
     for child in children: 
      for k,v in xml_to_dictionary(child).items(): 
       if k in subdictionary: 
        if (isinstance(subdictionary[k], list)): 
         subdictionary[k].append(v) 
        else: 
         subdictionary[k] = [subdictionary[k], v] 
       else: 
        subdictionary[k] = v 
     if (dictionary[tag] == {}): 
      dictionary[tag] = subdictionary 
     else: 
      dictionary[tag] = [dictionary[tag], subdictionary] 
    if element.attrib: 
     attribs = {} 
     for k,v in element.attrib.items(): 
      attribs[k] = v 
     if (dictionary[tag] == {}): 
      dictionary[tag] = attribs 
     else: 
      dictionary[tag] = [dictionary[tag], attribs] 
    return dictionary 

नाम स्थान, xmlns स्ट्रिंग, ब्रेसिज़ भी शामिल है कि सभी टैग करने के लिए ElementTree पहले जोड़ता है, इसलिए यहां मैं इसे के रूप में वहाँ पूरे दस्तावेज

एनबी के लिए एक नाम का स्थान साफ़ कर दिया है कि मैं समायोजित कच्चे एक्सएमएल भी है, ताकि 'खाली' टैग सबसे एक 'पाठ संपत्ति में ElementTree प्रतिनिधित्व

spacepattern = re.compile(r'\s+') 
mydictionary = xml_to_dictionary(ElementTree.XML(spacepattern.sub(' ', content))) 

में उत्पादन होता है उदाहरण के लिए देना होगा

{'note': {'to': 'Tove', 
     'from': 'Jani', 
     'heading': 'Reminder', 
     'body': "Don't forget me this weekend!"}} 

यह विशिष्ट एक्सएमएल कि मूल रूप से json के बराबर है के लिए बनाया गया है, तत्व संभाल चाहिए विशेषता शब्दकोश/subtag शब्दकोश विलय की संभावना है इस तरह के

<elementName attributeName='attributeContent'>elementContent</elementName> 
भी

के रूप में जिम्मेदार बताते हैं इसी तरह कैसे दोहराने subtags को विलय कर रहे हैं, हालांकि सूचियों को घोंसला करना उचित लगता है :-)

0

एक्सएमएल में एक समृद्ध इंफोसेट है, और इसे पाइथन शब्दकोश में प्रतिनिधित्व करने के लिए कुछ विशेष चालें होती हैं। तत्वों का आदेश दिया गया है, तत्वों को तत्व निकायों, आदि से अलग किया जाता है।

एक्सएमएल और पायथन शब्दकोशों के बीच राउंड-ट्रिप को संभालने के लिए एक परियोजना, विभिन्न तरीकों से ट्रेडऑफ को संभालने के लिए कुछ कॉन्फ़िगरेशन विकल्पों के साथ XML Support in Pickling Tools है। संस्करण 1.3 और नए की आवश्यकता है। यह शुद्ध पायथन नहीं है (और वास्तव में सी ++/पायथन इंटरैक्शन को आसान बनाने के लिए डिज़ाइन किया गया है), लेकिन यह विभिन्न उपयोग मामलों के लिए उपयुक्त हो सकता है।

1

में इस लाइन

d.update(('@' + k, v) for k, v in el.attrib.iteritems()) 

जोड़ना user247686's code आप नोड भी जिम्मेदार बताते हैं हो सकता है।

इस पोस्ट में यह पाया https://stackoverflow.com/a/7684581/1395962

उदाहरण:

import xml.etree.ElementTree as etree 
from urllib import urlopen 

xml_file = "http://your_xml_url" 
tree = etree.parse(urlopen(xml_file)) 
root = tree.getroot() 

def xml_to_dict(el): 
    d={} 
    if el.text: 
     d[el.tag] = el.text 
    else: 
     d[el.tag] = {} 
    children = el.getchildren() 
    if children: 
     d[el.tag] = map(xml_to_dict, children) 

    d.update(('@' + k, v) for k, v in el.attrib.iteritems()) 

    return d 

के रूप में कॉल

xml_to_dict(root) 
संबंधित मुद्दे