2014-02-10 7 views
2

xmltodict로 XML을 생성하려고합니다. 이렇게하려면 OrderedDict를 기반으로 구조체를 생성해야합니다. 처음 ".xml()"메서드를 실행할 때 예상되는 동작을 얻지 만 두 번째 시간을 실행하면 자식 요소가 두 번째로 추가됩니다.왜 재사용 방법에 문제가 있습니까?

from collections import OrderedDict 
import xmltodict 

class XMLObject(object): 
    __ns__ = '' 
    def __init__(self, parent=None, **kwargs): 
     self.parent = None 
     if parent: 
      self.__ns__ = parent.__ns__ 
      self.parent = parent 
     self._attrib = OrderedDict() 
     self.children = [] 

    def __setitem__(self, key, value): 
     self._attrib[key] = value 

    def __getitem__(self, item): 
     return self._attrib[item] 

    @property 
    def tagname(self): 
     return (self.__ns__ + ':' + self.__tag__) if self.__ns__ else self.__tag__ 

    def object(self): 
     store = OrderedDict() 
     print id(store) 
     tag = self.tagname 
     print tag 
     store[tag] = self._attrib 
     print self.children 
     for child in self.children: 
      print "-" + child.tagname 
      if not child.tagname in store[tag]: 
       store[tag][child.tagname] = list() 
      store[tag][child.tagname].append(child.object()[child.tagname]) 
     return store 

    def xml(self, pretty=False, clean=False): 
     xml = xmltodict.unparse(self.object()) 
     return xml 


class A(XMLObject): 
    __tag__ = 'A' 

    def __init__(self, *args, **kwargs): 
     super(A, self).__init__(*args, **kwargs) 
     self.children = [B(parent=self)] 


class B(XMLObject): 
    __tag__ = 'B' 

if __name__ == '__main__': 
    obj = A() 
    print obj.xml() 
    print obj.xml() 
    print obj.xml() 

ipython 콘솔에서 이것은 결과입니다.

In [1]: from question import * 

In [2]: obj = A() 

In [3]: obj.xml() 
35393280 
A 
[<question.B object at 0x7f3bc226f890>] 
-B 
35394720 
B 
[] 
Out[3]: u'<?xml version="1.0" encoding="utf-8"?>\n<A><B></B></A>' 

In [4]: obj.xml() 
35487136 
A 
[<question.B object at 0x7f3bc226f890>] 
-B 
35487936 
B 
[] 
Out[4]: u'<?xml version="1.0" encoding="utf-8"?>\n<A><B></B><B></B></A>' 

In [5]: obj.xml() 
35487136 
A 
[<question.B object at 0x7f3bc226f890>] 
-B 
35488896 
B 
[] 
Out[5]: u'<?xml version="1.0" encoding="utf-8"?>\n<A><B></B><B></B><B></B></A>' 

답변

3

당신은 당신의 OrderedDict()self._attrib에 대한 참조를 저장하는 :

store[tag] = self._attrib 

을이 복사되지 않습니다; 여기서 store 오브젝트로 인스턴스 속성을 공유하고 있습니다. 나중에 사전에 추가 할 때

그래서, 당신은 무엇을 self._attrib같은 객체을 변경하는은을 참조한다 : 당신은이 상태를 재설정하지 않는

if not child.tagname in store[tag]: 
    store[tag][child.tagname] = list() 
store[tag][child.tagname].append(child.object()[child.tagname]) 

; self._attrib remains altered when A.xml()`이 반환됩니다.

당신은 대부분 거기 self._attrib 객체의 사본을 사용하고 싶었 :이 얕은 복사본을 생성

store[tag] = self._attrib.copy() 

; self._attrib에있는 변경 가능한 객체에 대한 참조는 방금 복사됩니다. copy.deepcopy()을 사용하십시오. 재귀적인 딥 카피를 생성한다.

+0

네, 그 대답입니다. FTR : store [tag] = self._attrib는 store 여야합니다. [tag] = copy.copy (self._attrib) 다시 한 번 고맙습니다. – luisfernando

+0

@luisfernando :'copy.copy()'는 얕은 복사본을 만듭니다. 'dict' 객체 ('OrderdDict()'포함)에는'.copy()'메소드가 있습니다. –