2013-06-18 4 views
6

xml을 처리하기 위해 dict 클래스를 만들려고 노력하고 있지만, 실제로 아이디어가 부족합니다. 누군가가이 주제에 관해 안내 할 수 있다면 좋을 것입니다. 당신은xml을 python dict로 변환

https://github.com/martinblech/xmltodict

를 체크 아웃해야

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

희망이 도움 : 당신이 그것을 사용하는 방법

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 

이는 다음과 같습니다 유래에 비슷한 질문 다스의 절반을 검토 한 후, 여기에 나를 위해 일한 것입니다 이 질문은 이전에 대답되었습니다 : http://stackoverflow.com/questions/2148119/how-to-convert-an-xml-string-to-a-dictionary-in-python – robjohncox

+1

원하는 출력은 무엇입니까? ? – alecxe

+0

@Josh 나는 당신의 생각 친구를 이해하지 못합니다. – funktasmas

답변

18
xmltodict 모듈의 사용

당신은 할 수 있습니다 : OrderedDict

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([(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'의 소스를 보지 않으시겠습니까? 그것은 깨끗하고 잘 주석 처리 된 Python 코드의 백 줄입니다. 그리고 그것은 누군가가 해답을 얻으려고 어떤 빠르고도 더러운 해킹보다 더 낫게 될 것입니다. – abarnert

+0

@abarnert는 모듈을 개발하는 방법을 보았습니다. 아마도 시작하는 것이 좋은 방법 일 것입니다. – funktasmas

5

나는 내가 본 DICT하기 위해 XML을위한 최상의 표준 핸들러의 하나라고 생각 :

코드는 지금까지 개발했다. 내가 당신 XML과 딕셔너리 절대적으로 호환 데이터 구조

가 아닌 경고해야하지만

+0

답변 해 주셔서 감사합니다. 나는 또한 완전히 호환되는 구조가 아니며, 과거처럼 빠른 해결책이 없다고 생각합니다. – funktasmas

+0

@funktasmas : 간단한 경우의 유일한 큰 문제는 XML 노드가 하위 노드뿐만 아니라 속성도 가질 수 있다는 것입니다. 그리고이를 표현하는 방법을 결정해야합니다. 'xmltodict'는 문제를 해결하는 한 가지 방법 인 이름에'@'접두어가 붙은 노드로 속성을 나타내지 만 다른 가능성도 있습니다 (예 :'__getitem__'을 가진 노드와'__getattr__'을 사용하는 attrs를 처리 할 수 ​​있습니다). – abarnert

0

당신은 lxml library를 사용할 수 있습니다. objectify.fromstring을 사용하여 문자열을 xml 개체로 변환 한 다음 개체 dir 메서드를 찾습니다. 예를 들어 :

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__ 

는 딕셔너리를 반환 딕셔너리에 XML 객체를 변환 : 내가 사용

{'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''} 

는 XML 문자열은 단지 실제 예를 보여 게이트웨이 PAYMENTECH 지불의 응답이다.

또한 위의 예는 재귀 적이 아니므로 dicts 내에 dicts가 있으면 재귀를 수행해야합니다. 난 당신이 사용할 수있는 쓴 재귀 함수를 참조하십시오

을 Heres
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가 사용되었습니다. Cheers!

3

당신은 지금까지 우리가이 질문에 대한 좋은 대답을 가지고 있다고 생각 하겠지만, 우리는 분명히하지 않았습니다.

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) 

그것이 :-)