2013-06-18 11 views
6

कनवर्ट करने के लिए मैं एक XML वर्ग को संसाधित करने की कोशिश कर रहा हूं लेकिन अटक गया हूं, मैं वास्तव में विचारों से बाहर हूं। अगर कोई इस विषय पर मार्गदर्शन कर सकता है तो वह बहुत अच्छा होगा।xml से python dict

कोड अब तक विकसित:

class XMLResponse(dict): 
    def __init__(self, xml): 
     self.result = True 
     self.message = '' 
     pass 

    def __setattr__(self, name, val): 
     self[name] = val 

    def __getattr__(self, name): 
     if name in self: 
      return self[name] 
     return None 

message="<?xml version="1.0"?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>" 
XMLResponse(message) 
+0

ऐसा प्रतीत होता है कि इस प्रश्न का उत्तर पहले दिया गया है: http://stackoverflow.com/questions/2148119/how-to-convert-an-xml-string-to-a-dictionary-in-python – robjohncox

+1

आपका वांछित आउटपुट क्या है ? – alecxe

+0

@ जोश मैं आपके विचार को नहीं समझता – funktasmas

उत्तर

18

आप कर सकते xmltodict मॉड्यूल के उपयोग:

import xmltodict 

message = """<?xml version="1.0"?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>""" 
print xmltodict.parse(message)['note'] 

जो एक OrderedDict पैदा करता है:

OrderedDict([(u'to', u'Tove'), (u'from', u'Jani'), (u'heading', u'Reminder'), (u'body', u"Don't forget me this weekend!")]) 

जो यदि आदेश कोई फर्क नहीं पड़ता है तो उसे dict में परिवर्तित किया जा सकता है:

print dict(xmltodict.parse(message)['note']) 

प्रिंटों:

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

मदद के लिए धन्यवाद, मैं वास्तव में इसकी सराहना करता हूं, लेकिन मैं अभी भी सोचता हूं या देख रहा हूं कि यह अतिरिक्त मॉड्यूल के बिना कैसे किया जाता है, मैं वैसे भी कोशिश करूंगा। – funktasmas

+2

@funktasmas: यदि आप देखना चाहते हैं कि अतिरिक्त मॉड्यूल के बिना इसे कैसे करना है, तो 'xmltodict' के स्रोत को क्यों न देखें? यह साफ, अच्छी तरह से टिप्पणी पायथन कोड की कुछ सौ लाइनें है। और यह निश्चित रूप से एसओ पर किसी उत्तर के लिए आने वाले किसी भी त्वरित और गंदे हैक से बेहतर होने जा रहा है। – abarnert

+0

@ बार्नर्ट बस देख रहा था कि वे मॉड्यूल कैसे विकसित करते हैं, शायद यह शुरू करने का एक अच्छा तरीका है। – funktasmas

5

आप

https://github.com/martinblech/xmltodict

चेकआउट चाहिए मुझे लगता है कि dict को मैंने देखा है एक्सएमएल के लिए सबसे अच्छा मानक संचालकों में से एक है।

हालांकि मैं तुम्हें एक्सएमएल और dict बिल्कुल संगत डेटा संरचनाओं

नहीं हैं चेतावनी दी है चाहिए
+0

आपके उत्तर के लिए धन्यवाद। मुझे लगता है कि पूरी तरह से संगत संरचनाएं भी नहीं हैं, और अतीत में जितनी तेजी से कोई समाधान नहीं है। – funktasmas

+0

@funktasmas: साधारण मामलों के लिए एकमात्र बड़ा मुद्दा यह है कि एक्सएमएल नोड्स में विशेषताओं के साथ-साथ उप-नोड्स भी हो सकते हैं, और आपको यह तय करना होगा कि इसका प्रतिनिधित्व कैसे किया जाए। 'xmltodict' उनके नाम पर' @ 'उपसर्ग के साथ नोड्स के रूप में गुणों का प्रतिनिधित्व करता है, जो समस्या को हल करने का एक तरीका है, लेकिन अन्य संभावनाएं हैं- उदाहरण के लिए, आप' __getitem__' के साथ नोड्स को प्रबंधित कर सकते हैं और '__getattr__' के साथ अटर्स को संभाल सकते हैं। – abarnert

0

आप lxml library उपयोग कर सकते हैं। objectify.fromstring का उपयोग करके स्ट्रिंग को xml ऑब्जेक्ट में कनवर्ट करें और फिर ऑब्जेक्ट डीआईआर विधि देखें। उदाहरण के लिए:

from lxml import objectify 

xml_string = """<?xml version="1.0" encoding="UTF-8"?><NewOrderResp><IndustryType></IndustryType><MessageType>R</MessageType><MerchantID>700000005894</MerchantID><TerminalID>0031</TerminalID><CardBrand>AMEX</CardBrand><AccountNum>3456732800000010</AccountNum><OrderID>TESTORDER1</OrderID><TxRefNum>55A69B278025130CD36B3A95435AA84DC45363</TxRefNum><TxRefIdx>10</TxRefIdx><ProcStatus>0</ProcStatus><ApprovalStatus>1</ApprovalStatus><RespCode></RespCode><AVSRespCode></AVSRespCode><CVV2RespCode></CVV2RespCode><AuthCode></AuthCode><RecurringAdviceCd></RecurringAdviceCd><CAVVRespCode></CAVVRespCode><StatusMsg></StatusMsg><RespMsg></RespMsg><HostRespCode></HostRespCode><HostAVSRespCode></HostAVSRespCode><HostCVV2RespCode></HostCVV2RespCode><CustomerRefNum>A51C5B2B1811E5991208</CustomerRefNum><CustomerName>BOB STEVEN</CustomerName><ProfileProcStatus>0</ProfileProcStatus><CustomerProfileMessage>Profile Created</CustomerProfileMessage><RespTime>13055</RespTime><PartialAuthOccurred></PartialAuthOccurred><RequestedAmount></RequestedAmount><RedeemedAmount></RedeemedAmount><RemainingBalance></RemainingBalance><CountryFraudFilterStatus></CountryFraudFilterStatus><IsoCountryCode></IsoCountryCode></NewOrderResp>""" 

xml_object = objectify.fromstring(xml_string) 

print xml_object.__dict__ 

dict के लिए एक्सएमएल वस्तु परिवर्तित एक dict वापसी होगी:

{'RemainingBalance': u'', 'AVSRespCode': u'', 'RequestedAmount': u'', 'AccountNum': 3456732800000010, 'IsoCountryCode': u'', 'HostCVV2RespCode': u'', 'TerminalID': 31, 'CVV2RespCode': u'', 'RespMsg': u'', 'CardBrand': 'AMEX', 'MerchantID': 700000005894, 'RespCode': u'', 'ProfileProcStatus': 0, 'CustomerName': 'BOB STEVEN', 'PartialAuthOccurred': u'', 'MessageType': 'R', 'ProcStatus': 0, 'TxRefIdx': 10, 'RecurringAdviceCd': u'', 'IndustryType': u'', 'OrderID': 'TESTORDER1', 'StatusMsg': u'', 'ApprovalStatus': 1, 'RedeemedAmount': u'', 'CountryFraudFilterStatus': u'', 'TxRefNum': '55A69B278025130CD36B3A95435AA84DC45363', 'CustomerRefNum': 'A51C5B2B1811E5991208', 'CustomerProfileMessage': 'Profile Created', 'AuthCode': u'', 'RespTime': 13055, 'HostAVSRespCode': u'', 'CAVVRespCode': u'', 'HostRespCode': u''} 

एक्सएमएल स्ट्रिंग मैं इस्तेमाल किया सिर्फ एक वास्तविक दुनिया उदाहरण दिखाने के लिए प्रवेश द्वार Paymentech भुगतान से एक प्रतिक्रिया है।

यह भी ध्यान दें कि उपरोक्त उदाहरण रिकर्सिव नहीं है, इसलिए यदि डिक्ट्स के अंदर डिक्ट्स हैं तो आपको कुछ रिकर्सन करना होगा। पुनरावर्ती क्रिया मैंने लिखा है कि आप उपयोग कर सकते हैं:

from lxml import objectify 

def xml_to_dict_recursion(xml_object): 
    dict_object = xml_object.__dict__ 
    if not dict_object: 
     return xml_object 
    for key, value in dict_object.items(): 
     dict_object[key] = xml_to_dict_recursion(value) 
    return dict_object 

def xml_to_dict(xml_str): 
    return xml_to_dict_recursion(objectify.fromstring(xml_str)) 

xml_string = """<?xml version="1.0" encoding="UTF-8"?><Response><NewOrderResp> 
<IndustryType>Test</IndustryType><SomeData><SomeNestedData1>1234</SomeNestedData1> 
<SomeNestedData2>3455</SomeNestedData2></SomeData></NewOrderResp></Response>""" 

print xml_to_dict(xml_string) 
यहाँ

एक संस्करण है कि माता-पिता कुंजी/तत्व को बरकरार रखता है:

def xml_to_dict(xml_str): 
    """ Convert xml to dict, using lxml v3.4.2 xml processing library, see http://lxml.de/ """ 
    def xml_to_dict_recursion(xml_object): 
     dict_object = xml_object.__dict__ 
     if not dict_object: # if empty dict returned 
      return xml_object 
     for key, value in dict_object.items(): 
      dict_object[key] = xml_to_dict_recursion(value) 
     return dict_object 
    xml_obj = objectify.fromstring(xml_str) 
    return {xml_obj.tag: xml_to_dict_recursion(xml_obj)} 

और आप केवल एक सबट्री लौट सकते हैं और dict करने के लिए इसे परिवर्तित करना चाहते हैं, तो , आप Element.find (उपयोग कर सकते हैं):

xml_obj.find('.//') # lxml.objectify.ObjectifiedElement instance 

कई विकल्प यह पूरा करने के हैं, लेकिन यह एक महान अगर आप पहले से lxml का उपयोग कर रहे है। इस उदाहरण में lxml-3.4.2 का उपयोग किया गया था। चेयर!

3

आपको लगता है कि अब तक हम इसका एक अच्छा जवाब देंगे, लेकिन हमने स्पष्ट रूप से नहीं किया। stackoverflow पर इसी तरह के सवाल के दर्जन के आधे समीक्षा करने के बाद, यहाँ क्या मेरे लिए काम किया है:

from lxml import etree 
# arrow is an awesome lib for dealing with dates in python 
import arrow 


# converts an etree to dict, useful to convert xml to dict 
def etree2dict(tree): 
    root, contents = recursive_dict(tree) 
    return {root: contents} 


def recursive_dict(element): 
    if element.attrib and 'type' in element.attrib and element.attrib['type'] == "array": 
     return element.tag, [(dict(map(recursive_dict, child)) or getElementValue(child)) for child in element] 
    else: 
     return element.tag, dict(map(recursive_dict, element)) or getElementValue(element) 


def getElementValue(element): 
    if element.text: 
     if element.attrib and 'type' in element.attrib: 
      attr_type = element.attrib.get('type') 
      if attr_type == 'integer': 
       return int(element.text.strip()) 
      if attr_type == 'float': 
       return float(element.text.strip()) 
      if attr_type == 'boolean': 
       return element.text.lower().strip() == 'true' 
      if attr_type == 'datetime': 
       return arrow.get(element.text.strip()).timestamp 
     else: 
      return element.text 
    elif element.attrib: 
     if 'nil' in element.attrib: 
      return None 
     else: 
      return element.attrib 
    else: 
     return None 

और यह है कि इसका प्रयोग कैसे:

from lxml import etree 

message="""<?xml version="1.0"?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"'' 
tree = etree.fromstring(message) 
etree2dict(tree) 

आशा है कि यह मदद करता है :-)