2010-07-20 4 views
4

파이썬 2.4.4를 사용하여 XML을 파이썬 사전과 파이썬 사전을 변환해야합니다. 내가 필요로하는 것은 노드 이름과 값뿐입니다. 구문 분석하는 XML에 아무 것도 없기 때문에 속성에 대해 걱정하지 않아도됩니다. ElementTree은 2.4.4에서 사용할 수 없기 때문에 사용할 수 없으며 제 작업 환경으로 인해 제 3 자 라이브러리를 사용할 수 없습니다. 이 작업을 수행하는 가장 쉬운 방법은 무엇입니까? 좋은 발췌 문장이 있습니까?파이썬 사전과 XML을/

또한 쉬운 방법이 없다면 Python 2.4.4가 기본적으로 지원하는 대체 직렬화 형식이 있습니까?

답변

3

질문 Serialize Python dictionary to XML은 XML 직렬화의 몇 가지 방법을 나열합니다. 대체 직렬화 형식에 관해서는, pickle 모듈이 좋은 도구라고 생각합니다.

+1

나를 위해 옵션을 선택하지 않습니다 그 중 3/4은 외부 라이브러리입니다 그 질문에 :

from xml.dom.minidom import Document class DictToXML(object): default_list_item_name = "item" def __init__(self, structure, list_mappings={}): self.doc = Document() if len(structure) == 1: rootName = str(list(structure.keys())[0]) self.root = self.doc.createElement(rootName) self.list_mappings = list_mappings self.doc.appendChild(self.root) self.build(self.root, structure[rootName]) def build(self, father, structure): if type(structure) == dict: for k in structure: tag = self.doc.createElement(k) father.appendChild(tag) self.build(tag, structure[k]) elif type(structure) == list: tag_name = self.default_list_item_name if father.tagName in self.list_mappings: tag_name = self.list_mappings[father.tagName] for l in structure: tag = self.doc.createElement(tag_name) self.build(tag, l) father.appendChild(tag) else: data = str(structure) tag = self.doc.createTextNode(data) father.appendChild(tag) def display(self): print(self.doc.toprettyxml(indent=" ")) def get_string(self): return self.doc.toprettyxml(indent=" ") if __name__ == '__main__': example = {'sibling': {'couple': {'mother': 'mom', 'father': 'dad', 'children': [{'child': 'foo'}, {'child': 'bar'}]}}} xml = DictToXML(example) xml.display() 

그것은 다음과 같은 출력을 제공합니다. 마지막 하나는 XML 문서를 마샬링합니다.이 문서는 내가 찾고있는 문서가 아니지만 사전을 먼저 변환하여 보일 것입니다. – Liam

1

그레이의 링크에는 상당히 견고한 몇 가지 솔루션이 포함되어 있습니다. 스스로 롤업하려면 xml.dom.node의 childNode 멤버를 재귀 적으로 사용할 수 있으며 node.childNode = None 일 때 종료됩니다.

5

필자는 XML을 파이썬 데이터 구조로 변환하는 코드를 작성했습니다.하지만 특성을 처리해야했습니다. 비슷한 이유로 ElementTree 대신 xml.dom.minidom을 사용했습니다. 필자는 Python 2.4.4에서 이것을 실제로 테스트하지는 않았지만 작동 할 것이라고 생각합니다. 역방향 XML 생성기를 작성하지 않았지만, 아마도 이것을 포함하기 위해 'lispy_string'함수를 사용할 수 있습니다.

필자가 작성한 응용 프로그램과 관련된 몇 가지 바로 가기가 포함되어 있지만 (문서화 스트링에 설명되어 있음),이 바로 가기도 소리를 통해 유용하게 사용할 수 있습니다. 본질적으로 xml 트리는 기술적으로 사전 목록 등 사전의 사전 목록으로 번역됩니다. 필요하지 않으면 중개 목록을 작성하지 않으므로 dictname[element1][0][element2][0] 대신 dictname[element1][element2] 등의 요소를 참조 할 수 있습니다.

특성 처리는 다소 번거롭기 때문에 속성을 사용하기 전에 코드를 읽는 것이 좋습니다.

import sys 
from xml.dom import minidom 

def dappend(dictionary, key, item): 
    """Append item to dictionary at key. Only create a list if there is more than one item for the given key. 
    dictionary[key]=item if key doesn't exist. 
    dictionary[key].append(item) if key exists.""" 
    if key in dictionary.keys(): 
     if not isinstance(dictionary[key], list): 
      lst=[] 
      lst.append(dictionary[key]) 
      lst.append(item) 
      dictionary[key]=lst 
     else: 
      dictionary[key].append(item) 
    else: 
     dictionary.setdefault(key, item) 

def node_attributes(node): 
    """Return an attribute dictionary """ 
    if node.hasAttributes(): 
     return dict([(str(attr), str(node.attributes[attr].value)) for attr in node.attributes.keys()]) 
    else: 
     return None 

def attr_str(node): 
    return "%s-attrs" % str(node.nodeName) 

def hasAttributes(node): 
    if node.nodeType == node.ELEMENT_NODE: 
     if node.hasAttributes(): 
      return True 
    return False 

def with_attributes(node, values): 
    if hasAttributes(node): 
     if isinstance(values, dict): 
      dappend(values, '#attributes', node_attributes(node)) 
      return { str(node.nodeName): values } 
     elif isinstance(values, str): 
      return { str(node.nodeName): values, 
        attr_str(node): node_attributes(node)} 
    else: 
     return { str(node.nodeName): values } 

def xmldom2dict(node): 
    """Given an xml dom node tree, 
    return a python dictionary corresponding to the tree structure of the XML. 
    This parser does not make lists unless they are needed. For example: 

    '<list><item>1</item><item>2</item></list>' becomes: 
    { 'list' : { 'item' : ['1', '2'] } } 
    BUT 
    '<list><item>1</item></list>' would be: 
    { 'list' : { 'item' : '1' } } 

    This is a shortcut for a particular problem and probably not a good long-term design. 
    """ 
    if not node.hasChildNodes(): 
     if node.nodeType == node.TEXT_NODE: 
      if node.data.strip() != '': 
       return str(node.data.strip()) 
      else: 
       return None 
     else: 
      return with_attributes(node, None) 
    else: 
     #recursively create the list of child nodes 
     childlist=[xmldom2dict(child) for child in node.childNodes if (xmldom2dict(child) != None and child.nodeType != child.COMMENT_NODE)] 
     if len(childlist)==1: 
      return with_attributes(node, childlist[0]) 
     else: 
      #if False not in [isinstance(child, dict) for child in childlist]: 
      new_dict={} 
      for child in childlist: 
       if isinstance(child, dict): 
        for k in child: 
         dappend(new_dict, k, child[k]) 
       elif isinstance(child, str): 
        dappend(new_dict, '#text', child) 
       else: 
        print "ERROR" 
      return with_attributes(node, new_dict) 

def load(fname): 
    return xmldom2dict(minidom.parse(fname)) 

def lispy_string(node, lst=None, level=0): 
    if lst==None: 
     lst=[] 
    if not isinstance(node, dict) and not isinstance(node, list): 
     lst.append(' "%s"' % node) 
    elif isinstance(node, dict): 
     for key in node.keys(): 
      lst.append("\n%s(%s" % (spaces(level), key)) 
      lispy_print(node[key], lst, level+2) 
      lst.append(")") 
    elif isinstance(node, list): 
     lst.append(" [") 
     for item in node: 
      lispy_print(item, lst, level) 
     lst.append("]") 
    return lst 

if __name__=='__main__': 
    data = minidom.parse(sys.argv[1]) 

    d=xmldom2dict(data) 

    print d 
+0

이것은 좋은 예입니다. 감사! – rsmoorthy

+0

추가 기능을 포함하도록 약간 수정했으며, http://pastebin.com/rtDQsR2j – rsmoorthy

+0

에 있습니다. 감사! –

2

Dicts in python은 주문하지 않았으므로 기억하십시오. 나는 매우 작고 외부 모듈을 필요로하지 않는 매우 기본적인 코드를 가지고있다. 나쁜 점은 XML 속성의 어떤 종류를 지원하지 않는다는 것입니다,하지만 당신은 그렇게 여기있다

내가, 속성

에 대해 걱정하지 않아요 말했다 :

def d2x(d, root="root"): 

    op = lambda tag: '<' + tag + '>' 
    cl = lambda tag: '</' + tag + '>\n' 
    ml = lambda v,xml: xml + op(key) + str(v) + cl(key) 

    xml = op(root) + '\n' if root else "" 

    for key,vl in d.iteritems(): 
     vtype = type(vl) 
     if vtype is list: 
      for v in vl: 
       xml = ml(v,xml)   
     if vtype is dict: xml = ml('\n' + d2x(vl,None),xml)   
     if vtype is not list and vtype is not dict: xml = ml(vl,xml) 

    xml += cl(root) if root else "" 

    return xml 

예 사용의 :

mydict = { 
"boolean":False, 
"integer":12, 
"float":3.1, 
"listitems":["item1","item2"], 
"string":"Hello world", 
"dictionary":{ 
    "key1":1, 
    "key2":2, 
    "dictindict":{ 
       "a":"aaa", 
       "b":"bbb" 
       } 
      } 
} 
print d2x (mydict,"superxml") 

이 인쇄됩니다 :

<superxml> 
<string>Hello world</string> 
<dictionary> 
<key2>2</key2> 
<key1>1</key1> 
<dictindict> 
<a>aaa</a> 
<b>bbb</b> 
</dictindict> 
</dictionary> 
<float>3.1</float> 
<listitems>item1</listitems> 
<listitems>item2</listitems> 
<boolean>False</boolean> 
<integer>12</integer> 
</superxml> 
1

파이썬 사전을 XML로 직렬화하려면 다음 Python 클래스가 적합합니다. 일부 다른 솔루션에 비해 매우 간단하고 적절한 XML 인코딩을 수행 할 수 있다는 장점이 있습니다. 스크립트는 this answer을 기반으로합니다. 여기에는 하나의 확장자 만 있습니다. list_mappings 사전을 생성자에 전달하여 단일 목록 항목 (아래 예에서 children 속성에있는 child)의 이름 지정 방법을 지정할 수 있습니다.

<?xml version="1.0" ?> 
<sibling> 
    <couple> 
    <children> 
     <child> 
     <name>foo</name> 
     </child> 
     <child> 
     <name>bar</name> 
     </child> 
    </children> 
    <father>dad</father> 
    <mother>mom</mother> 
    </couple> 
</sibling> 
+0

패키지 [dicttoxml] (https://pypi.python.org/pypi/dicttoxml) 패키지가 이미 있습니다. 파이썬 패키지 인덱스에 나열되어 있고 잘 문서화되어 있기 때문에 이것을 사용하는 것이 좋습니다. – philosopher

관련 문제