[PYTHON] 파이썬에서 XML 문자열을 사전으로 변환하는 방법은 무엇입니까?
PYTHON파이썬에서 XML 문자열을 사전으로 변환하는 방법은 무엇입니까?
소켓에서 XML 문서를 읽는 프로그램이 있습니다. XML 문서를 장고의 simplejson 라이브러리에서와 같은 방식으로 Python 사전으로 직접 변환하고자하는 문자열에 저장했습니다.
예를 들면 다음과 같습니다.
str ="<?xml version="1.0" ?><person><name>john</name><age>20</age></person"
dic_xml = convert_to_dic(str)
그러면 dic_xml은 { 'person': { 'name': 'john', 'age': 20}}처럼 보일 것입니다.
해결법
-
==============================
1.이것은 누군가가 창조 한 위대한 모듈입니다. 나는 그것을 여러 번 사용했다. http://code.activestate.com/recipes/410469-xml-as-dictionary/
이것은 누군가가 창조 한 위대한 모듈입니다. 나는 그것을 여러 번 사용했다. http://code.activestate.com/recipes/410469-xml-as-dictionary/
링크가 잘못 될 경우에 대비하여 웹 사이트의 코드가 있습니다.
import cElementTree as ElementTree class XmlListConfig(list): def __init__(self, aList): for element in aList: if element: # treat like dict if len(element) == 1 or element[0].tag != element[1].tag: self.append(XmlDictConfig(element)) # treat like list elif element[0].tag == element[1].tag: self.append(XmlListConfig(element)) elif element.text: text = element.text.strip() if text: self.append(text) class XmlDictConfig(dict): ''' Example usage: >>> tree = ElementTree.parse('your_file.xml') >>> root = tree.getroot() >>> xmldict = XmlDictConfig(root) Or, if you want to use an XML string: >>> root = ElementTree.XML(xml_string) >>> xmldict = XmlDictConfig(root) And then use xmldict for what it is... a dict. ''' def __init__(self, parent_element): if parent_element.items(): self.update(dict(parent_element.items())) for element in parent_element: if element: # treat like dict - we assume that if the first two tags # in a series are different, then they are all different. if len(element) == 1 or element[0].tag != element[1].tag: aDict = XmlDictConfig(element) # treat like list - we assume that if the first two tags # in a series are the same, then the rest are the same. else: # here, we put the list in dictionary; the key is the # tag name the list elements all share in common, and # the value is the list itself aDict = {element[0].tag: XmlListConfig(element)} # if the tag has attributes, add those to the dict if element.items(): aDict.update(dict(element.items())) self.update({element.tag: aDict}) # this assumes that if you've got an attribute in a tag, # you won't be having any text. This may or may not be a # good idea -- time will tell. It works for the way we are # currently doing XML configuration files... elif element.items(): self.update({element.tag: dict(element.items())}) # finally, if there are no child tags and no attributes, extract # the text else: self.update({element.tag: element.text})
사용 예 :
tree = ElementTree.parse('your_file.xml') root = tree.getroot() xmldict = XmlDictConfig(root)
// 또는 XML 문자열을 사용하려는 경우 :
root = ElementTree.XML(xml_string) xmldict = XmlDictConfig(root)
-
==============================
2.xmltodict (전체 공개 : 나는 그것을 썼다.) 정확하게 그것을한다 :
xmltodict (전체 공개 : 나는 그것을 썼다.) 정확하게 그것을한다 :
xmltodict.parse(""" <?xml version="1.0" ?> <person> <name>john</name> <age>20</age> </person>""") # {u'person': {u'age': u'20', u'name': u'john'}}
-
==============================
3.다음 XML-to-Python-dict 스 니펫은이 XML-to-JSON "스펙"에 따라 속성뿐만 아니라 엔티티를 구문 분석합니다. 모든 XML 케이스를 처리하는 가장 일반적인 솔루션입니다.
다음 XML-to-Python-dict 스 니펫은이 XML-to-JSON "스펙"에 따라 속성뿐만 아니라 엔티티를 구문 분석합니다. 모든 XML 케이스를 처리하는 가장 일반적인 솔루션입니다.
from collections import defaultdict def etree_to_dict(t): d = {t.tag: {} if t.attrib else None} children = list(t) if children: dd = defaultdict(list) for dc in map(etree_to_dict, children): for k, v in dc.items(): dd[k].append(v) d = {t.tag: {k:v[0] if len(v) == 1 else v for k, v in dd.items()}} if t.attrib: d[t.tag].update(('@' + k, v) for k, v in t.attrib.items()) if t.text: text = t.text.strip() if children or t.attrib: if text: d[t.tag]['#text'] = text else: d[t.tag] = text return d
그것은 사용됩니다 :
from xml.etree import cElementTree as ET e = ET.XML(''' <root> <e /> <e>text</e> <e name="value" /> <e name="value">text</e> <e> <a>text</a> <b>text</b> </e> <e> <a>text</a> <a>text</a> </e> <e> text <a>text</a> </e> </root> ''') from pprint import pprint pprint(etree_to_dict(e))
이 예제의 결과 (위의 링크 된 "사양"에 따라)는 다음과 같아야합니다.
{'root': {'e': [None, 'text', {'@name': 'value'}, {'#text': 'text', '@name': 'value'}, {'a': 'text', 'b': 'text'}, {'a': ['text', 'text']}, {'#text': 'text', 'a': 'text'}]}}
꼭 필요한 것은 아니지만 모호하지 않으며 XML 입력이 단순 해지면 JSON이 단순 해집니다. :)
역순으로 처리하려면 JSON / dict에서 XML 문자열을 내보내고 다음을 사용할 수 있습니다.
try: basestring except NameError: # python3 basestring = str def dict_to_etree(d): def _to_etree(d, root): if not d: pass elif isinstance(d, basestring): root.text = d elif isinstance(d, dict): for k,v in d.items(): assert isinstance(k, basestring) if k.startswith('#'): assert k == '#text' and isinstance(v, basestring) root.text = v elif k.startswith('@'): assert isinstance(v, basestring) root.set(k[1:], v) elif isinstance(v, list): for e in v: _to_etree(e, ET.SubElement(root, k)) else: _to_etree(v, ET.SubElement(root, k)) else: raise TypeError('invalid type: ' + str(type(d))) assert isinstance(d, dict) and len(d) == 1 tag, body = next(iter(d.items())) node = ET.Element(tag) _to_etree(body, node) return ET.tostring(node) pprint(dict_to_etree(d))
-
==============================
4.이 가벼운 버전은 구성 할 수 없지만 필요에 따라 재구성하기 쉽고 오래된 비단뱀에서 작동합니다. 또한 속성은 속성의 존재 여부와 관계없이 결과가 동일 함을 의미합니다.
이 가벼운 버전은 구성 할 수 없지만 필요에 따라 재구성하기 쉽고 오래된 비단뱀에서 작동합니다. 또한 속성은 속성의 존재 여부와 관계없이 결과가 동일 함을 의미합니다.
import xml.etree.ElementTree as ET from copy import copy def dictify(r,root=True): if root: return {r.tag : dictify(r, False)} d=copy(r.attrib) if r.text: d["_text"]=r.text for x in r.findall("./*"): if x.tag not in d: d[x.tag]=[] d[x.tag].append(dictify(x,False)) return d
그래서:
root = ET.fromstring("<erik><a x='1'>v</a><a y='2'>w</a></erik>") dictify(root)
결과 :
{'erik': {'a': [{'x': '1', '_text': 'v'}, {'y': '2', '_text': 'w'}]}}
-
==============================
5.PicklingTools 라이브러리 (1.3.0 및 1.3.1)의 최신 버전은 XML에서 Python dict로 변환하는 도구를 지원합니다.
PicklingTools 라이브러리 (1.3.0 및 1.3.1)의 최신 버전은 XML에서 Python dict로 변환하는 도구를 지원합니다.
다운로드는 여기에서 사용할 수 있습니다 : PicklingTools 1.3.1
여기에는 변환기에 대한 문서가 많이 있습니다. 설명서에는 XML과 Python 사전간에 변환 할 때 발생할 수있는 모든 결정과 문제가 자세하게 설명되어 있습니다 (특성, 목록, 익명 목록, 익명 목록, 익명 목록 등) dicts, eval 등 대부분의 변환기가 처리하지 못함). 하지만 일반적으로, 변환기는 사용하기 쉽습니다. 'example.xml'에 다음이 포함 된 경우 :
<top> <a>1</a> <b>2.2</b> <c>three</c> </top>
그런 다음 사전으로 변환하려면 다음을 수행하십시오.
>>> from xmlloader import * >>> example = file('example.xml', 'r') # A document containing XML >>> xl = StreamXMLLoader(example, 0) # 0 = all defaults on operation >>> result = xl.expect XML() >>> print result {'top': {'a': '1', 'c': 'three', 'b': '2.2'}}
C ++과 Python 모두에서 변환 할 수있는 도구가 있습니다. C ++과 Python은 변환을 수행하지만 C ++은 약 60 배 더 빠릅니다.
-
==============================
6.lxml로 이것을 아주 쉽게 할 수 있습니다. 먼저 설치하십시오.
lxml로 이것을 아주 쉽게 할 수 있습니다. 먼저 설치하십시오.
[sudo] pip install lxml
여기에 당신을 위해 힘든 일을하는 쓴 재귀 함수가 있습니다 :
from lxml import objectify as xml_objectify def xml_to_dict(xml_str): """ Convert xml to dict, using lxml v3.4.2 xml processing library """ 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 return xml_to_dict_recursion(xml_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 문서를 참조하십시오. 이게 도움이 되길 바란다!
-
==============================
7.Python 용 XML 파서를 사용하는 가장 쉬운 방법은 ElementTree (2.5x 이상은 표준 라이브러리 xml.etree.ElementTree에 있습니다)입니다. 상자에서 원하는 것을 정확하게하는 것은 아무것도 없다고 생각합니다. ElementTree를 사용하여 원하는 것을 수행하기 위해 무언가를 쓰는 것이 쉽지만 사전으로 변환하는 이유는 무엇이며 왜 ElementTree를 직접 사용하지 않는가?
Python 용 XML 파서를 사용하는 가장 쉬운 방법은 ElementTree (2.5x 이상은 표준 라이브러리 xml.etree.ElementTree에 있습니다)입니다. 상자에서 원하는 것을 정확하게하는 것은 아무것도 없다고 생각합니다. ElementTree를 사용하여 원하는 것을 수행하기 위해 무언가를 쓰는 것이 쉽지만 사전으로 변환하는 이유는 무엇이며 왜 ElementTree를 직접 사용하지 않는가?
-
==============================
8.
def xml_to_dict(node): u''' @param node:lxml_node @return: dict ''' return {'tag': node.tag, 'text': node.text, 'attrib': node.attrib, 'children': {child.tag: xml_to_dict(child) for child in node}}
-
==============================
9.http://code.activestate.com/recipes/410469-xml-as-dictionary/의 코드는 잘 작동하지만, 계층 구조의 주어진 위치에서 동일한 여러 요소가있는 경우이를 오버라이드합니다.
http://code.activestate.com/recipes/410469-xml-as-dictionary/의 코드는 잘 작동하지만, 계층 구조의 주어진 위치에서 동일한 여러 요소가있는 경우이를 오버라이드합니다.
그 사이에 shim을 추가하여 self.update () 전에 요소가 이미 있는지 확인합니다. 그렇다면 기존 항목을 팝하고 기존 항목과 새 항목 목록을 만듭니다. 이후의 모든 중복이 목록에 추가됩니다.
이것이 더 정상적으로 처리 될 수 있는지 확실하지 않지만 작동합니다.
import xml.etree.ElementTree as ElementTree class XmlDictConfig(dict): def __init__(self, parent_element): if parent_element.items(): self.updateShim(dict(parent_element.items())) for element in parent_element: if len(element): aDict = XmlDictConfig(element) if element.items(): aDict.updateShim(dict(element.items())) self.updateShim({element.tag: aDict}) elif element.items(): self.updateShim({element.tag: dict(element.items())}) else: self.updateShim({element.tag: element.text.strip()}) def updateShim (self, aDict ): for key in aDict.keys(): if key in self: value = self.pop(key) if type(value) is not list: listOfDicts = [] listOfDicts.append(value) listOfDicts.append(aDict[key]) self.update({key: listOfDicts}) else: value.append(aDict[key]) self.update({key: value}) else: self.update(aDict)
-
==============================
10.@ K3 --- rnc 응답 (나에게 최상)부터 XML 텍스트에서 OrderedDict를 얻는 작은 수정 사항을 추가했습니다 (때로는 순서가 중요합니다).
@ K3 --- rnc 응답 (나에게 최상)부터 XML 텍스트에서 OrderedDict를 얻는 작은 수정 사항을 추가했습니다 (때로는 순서가 중요합니다).
def etree_to_ordereddict(t): d = OrderedDict() d[t.tag] = OrderedDict() if t.attrib else None children = list(t) if children: dd = OrderedDict() for dc in map(etree_to_ordereddict, children): for k, v in dc.iteritems(): if k not in dd: dd[k] = list() dd[k].append(v) d = OrderedDict() d[t.tag] = OrderedDict() for k, v in dd.iteritems(): if len(v) == 1: d[t.tag][k] = v[0] else: d[t.tag][k] = v if t.attrib: d[t.tag].update(('@' + k, v) for k, v in t.attrib.iteritems()) if t.text: text = t.text.strip() if children or t.attrib: if text: d[t.tag]['#text'] = text else: d[t.tag] = text return d
@ K3 --- rnc 예제를 따르면 다음과 같이 사용할 수 있습니다.
from xml.etree import cElementTree as ET e = ET.XML(''' <root> <e /> <e>text</e> <e name="value" /> <e name="value">text</e> <e> <a>text</a> <b>text</b> </e> <e> <a>text</a> <a>text</a> </e> <e> text <a>text</a> </e> </root> ''') from pprint import pprint pprint(etree_to_ordereddict(e))
희망이 도움이;)
-
==============================
11.부인 성명: 이 수정 된 XML 구문 분석기는 Adam Clark에서 영감을 얻었습니다. 원본 XML 파서는 대부분의 간단한 경우에 사용할 수 있습니다. 그러나 일부 복잡한 XML 파일에서는 작동하지 않습니다. 코드를 한 줄씩 디버깅하고 마침내 문제를 해결했습니다. 버그를 발견하면 알려주세요. 나는 그것을 고칠 수있어 기쁘다.
부인 성명: 이 수정 된 XML 구문 분석기는 Adam Clark에서 영감을 얻었습니다. 원본 XML 파서는 대부분의 간단한 경우에 사용할 수 있습니다. 그러나 일부 복잡한 XML 파일에서는 작동하지 않습니다. 코드를 한 줄씩 디버깅하고 마침내 문제를 해결했습니다. 버그를 발견하면 알려주세요. 나는 그것을 고칠 수있어 기쁘다.
class XmlDictConfig(dict): ''' Note: need to add a root into if no exising Example usage: >>> tree = ElementTree.parse('your_file.xml') >>> root = tree.getroot() >>> xmldict = XmlDictConfig(root) Or, if you want to use an XML string: >>> root = ElementTree.XML(xml_string) >>> xmldict = XmlDictConfig(root) And then use xmldict for what it is... a dict. ''' def __init__(self, parent_element): if parent_element.items(): self.updateShim( dict(parent_element.items()) ) for element in parent_element: if len(element): aDict = XmlDictConfig(element) # if element.items(): # aDict.updateShim(dict(element.items())) self.updateShim({element.tag: aDict}) elif element.items(): # items() is specialy for attribtes elementattrib= element.items() if element.text: elementattrib.append((element.tag,element.text )) # add tag:text if there exist self.updateShim({element.tag: dict(elementattrib)}) else: self.updateShim({element.tag: element.text}) def updateShim (self, aDict ): for key in aDict.keys(): # keys() includes tag and attributes if key in self: value = self.pop(key) if type(value) is not list: listOfDicts = [] listOfDicts.append(value) listOfDicts.append(aDict[key]) self.update({key: listOfDicts}) else: value.append(aDict[key]) self.update({key: value}) else: self.update({key:aDict[key]}) # it was self.update(aDict)
-
==============================
12.다음은 ActiveState 솔루션에 대한 링크입니다 - 코드가 다시 사라질 경우를 대비하여.
다음은 ActiveState 솔루션에 대한 링크입니다 - 코드가 다시 사라질 경우를 대비하여.
================================================== xmlreader.py: ================================================== from xml.dom.minidom import parse class NotTextNodeError: pass def getTextFromNode(node): """ scans through all children of node and gathers the text. if node has non-text child-nodes, then NotTextNodeError is raised. """ t = "" for n in node.childNodes: if n.nodeType == n.TEXT_NODE: t += n.nodeValue else: raise NotTextNodeError return t def nodeToDic(node): """ nodeToDic() scans through the children of node and makes a dictionary from the content. three cases are differentiated: - if the node contains no other nodes, it is a text-node and {nodeName:text} is merged into the dictionary. - if the node has the attribute "method" set to "true", then it's children will be appended to a list and this list is merged to the dictionary in the form: {nodeName:list}. - else, nodeToDic() will call itself recursively on the nodes children (merging {nodeName:nodeToDic()} to the dictionary). """ dic = {} for n in node.childNodes: if n.nodeType != n.ELEMENT_NODE: continue if n.getAttribute("multiple") == "true": # node with multiple children: # put them in a list l = [] for c in n.childNodes: if c.nodeType != n.ELEMENT_NODE: continue l.append(nodeToDic(c)) dic.update({n.nodeName:l}) continue try: text = getTextFromNode(n) except NotTextNodeError: # 'normal' node dic.update({n.nodeName:nodeToDic(n)}) continue # text node dic.update({n.nodeName:text}) continue return dic def readConfig(filename): dom = parse(filename) return nodeToDic(dom) def test(): dic = readConfig("sample.xml") print dic["Config"]["Name"] print for item in dic["Config"]["Items"]: print "Item's Name:", item["Name"] print "Item's Value:", item["Value"] test() ================================================== sample.xml: ================================================== <?xml version="1.0" encoding="UTF-8"?> <Config> <Name>My Config File</Name> <Items multiple="true"> <Item> <Name>First Item</Name> <Value>Value 1</Value> </Item> <Item> <Name>Second Item</Name> <Value>Value 2</Value> </Item> </Items> </Config> ================================================== output: ================================================== My Config File Item's Name: First Item Item's Value: Value 1 Item's Name: Second Item Item's Value: Value 2
-
==============================
13.필자는 애트리뷰트가없는 요소로만 구성된 XML을 구문 분석하고 작성해야만 XML에서 dict 로의 1 : 1 매핑이 쉽게 가능했다. 이것은 누군가 다른 사람이 필요로하지 않는 경우를 생각해 냈습니다.
필자는 애트리뷰트가없는 요소로만 구성된 XML을 구문 분석하고 작성해야만 XML에서 dict 로의 1 : 1 매핑이 쉽게 가능했다. 이것은 누군가 다른 사람이 필요로하지 않는 경우를 생각해 냈습니다.
def xmltodict(element): if not isinstance(element, ElementTree.Element): raise ValueError("must pass xml.etree.ElementTree.Element object") def xmltodict_handler(parent_element): result = dict() for element in parent_element: if len(element): obj = xmltodict_handler(element) else: obj = element.text if result.get(element.tag): if hasattr(result[element.tag], "append"): result[element.tag].append(obj) else: result[element.tag] = [result[element.tag], obj] else: result[element.tag] = obj return result return {element.tag: xmltodict_handler(element)} def dicttoxml(element): if not isinstance(element, dict): raise ValueError("must pass dict type") if len(element) != 1: raise ValueError("dict must have exactly one root key") def dicttoxml_handler(result, key, value): if isinstance(value, list): for e in value: dicttoxml_handler(result, key, e) elif isinstance(value, basestring): elem = ElementTree.Element(key) elem.text = value result.append(elem) elif isinstance(value, int) or isinstance(value, float): elem = ElementTree.Element(key) elem.text = str(value) result.append(elem) elif value is None: result.append(ElementTree.Element(key)) else: res = ElementTree.Element(key) for k, v in value.items(): dicttoxml_handler(res, k, v) result.append(res) result = ElementTree.Element(element.keys()[0]) for key, value in element[element.keys()[0]].items(): dicttoxml_handler(result, key, value) return result def xmlfiletodict(filename): return xmltodict(ElementTree.parse(filename).getroot()) def dicttoxmlfile(element, filename): ElementTree.ElementTree(dicttoxml(element)).write(filename) def xmlstringtodict(xmlstring): return xmltodict(ElementTree.fromstring(xmlstring).getroot()) def dicttoxmlstring(element): return ElementTree.tostring(dicttoxml(element))
-
==============================
14.@dibrovsd : xml에 같은 이름의 태그가 두 개 이상있는 경우 솔루션이 작동하지 않습니다.
@dibrovsd : xml에 같은 이름의 태그가 두 개 이상있는 경우 솔루션이 작동하지 않습니다.
귀하의 생각에, 나는 코드를 조금 수정하고 루트 대신 일반 노드를 위해 작성했습니다.
from collections import defaultdict def xml2dict(node): d, count = defaultdict(list), 1 for i in node: d[i.tag + "_" + str(count)]['text'] = i.findtext('.')[0] d[i.tag + "_" + str(count)]['attrib'] = i.attrib # attrib gives the list d[i.tag + "_" + str(count)]['children'] = xml2dict(i) # it gives dict return d
-
==============================
15.lxml 요소에서 사전을 가져 오는 재귀 적 메서드가 있습니다.
lxml 요소에서 사전을 가져 오는 재귀 적 메서드가 있습니다.
def recursive_dict(element): return (element.tag.split('}')[1], dict(map(recursive_dict, element.getchildren()), **element.attrib))
from https://stackoverflow.com/questions/2148119/how-to-convert-an-xml-string-to-a-dictionary-in-python by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 파이썬 속성은 어떻게 작동합니까? (0) | 2018.10.03 |
---|---|
[PYTHON] 파이썬에서리스트에서 중복을 제거하는 가장 빠른 알고리즘은 무엇입니까? 그래서 모든 요소가 순차적으로 * 보존됩니다 *. [복제] (0) | 2018.10.03 |
[PYTHON] 파이썬 '자체'변수를 초급자에게 설명하기 [duplicate] (0) | 2018.10.03 |
[PYTHON] 이 파이썬 스 니펫에서 세미콜론이 허용되는 이유는 무엇입니까? (0) | 2018.10.03 |
[PYTHON] JSON 문자열을 사전이 아닌 목록으로 변환 (0) | 2018.10.03 |