2014-06-10 75 views
2

的Python列表這是一個示例XML文件內容,我有工作:解析XML文件字典

<states> 
    <state name="foo"> 
     <and> 
      <eq><text value="bar" /></eq> 
      <or> 
       <eqnull><text value="bar2" /></eqnull> 
       <eqnull><text value="bar3" /></eqnull> 
      </or> 
     </and> 
    </state> 
</states> 

這種結構是不可預測的,它可以在每個狀態截然改變。它可以,例如,是這樣的:

<states> 
    <state name="foo"> 
     <and> 
      <or> 
       <eq><text value="bar" /></eq> 
       <eq><text value="bar2" /></eq> 
      </or> 
      <eqnull><selectedText value="bar3" number="1"></eqnull> 
     </and> 
    </state> 
</states> 
從這種結構的不可預測性

獨立,我想將它解析到字典的Python列表,它看起來像這樣(相應於第一XML爲例):

[{'and': {'eq': {'text': {'value': 'bar'}}}}, 
{'and': {'or': [{'eqnull': {'text': {'value': 'bar2'}}}, 
       {'eqnull': {'text': {'value': 'bar3'}}},]}}] 

我試圖使用ElementTree的,並使用獲得的狀態結構的內容作爲字典:

xmltodict.parse 

然後遞歸地剝去該字典(按琴鍵)噸o我的字典清單。這個解決方案對我來說很難實現(不幸的是,我不是一個Python開發者......),如果有更簡單的方法來做這件事,我就會遊蕩。

我還記得另一個解決方案:遍歷XML結構中的每個節點,建立字典,最後是字典列表。但是有一個問題:當eq節點結束時我不知道。如果有某種方法可以識別結束節點/ eq,我認爲它是可以管理的。

或者,也許有一些是另一種方式在Python,對此我不知道的事情......

回答

0

下面是如何,你可以通過遞歸添加每個節點的內容做一個例子:

def findMarkup(str, mainlist): 
    markup = re.search('<([^>]*)>', str) 
    if markup: 
     markup_content = markup.group(1) 
     begin = markup.end() 
     name = markup_content.split(' ')[0] 
     #we check if the markup ends itself 
     if markup_content.find('/')!=-1: 
      end = begin+1 
     else: 
      end = str.find('</{0}>'.format(name)) 
     if begin+1<end: 
      #the node has child, its content is theirs 
      inner_value = [] 
      findMarkup(str[begin:end], inner_value) 
     else: 
      #the content of the current node is its attributes 
      inner_value = getAttr(markup_content) 
     #we add the content of the current node 
     mainlist.append({name:inner_value}) 

    #we iterate on the rest of the string for same level markups 
    findMarkup(str[end+2:],mainlist) 


def getAttr(markup_content): 
    attr_list = re.finditer('(\w*)="(\w*)"', markup_content) 
    attr_dict = dict() 
    for attr in attr_list: 
     attr_dict[attr.group(1)] = attr.group(2) 
    return attr_dict 

它給了我喜歡的東西(如果我看上去狀態裏面的內容,導致狀態也將被算作節點)

[{'and': [{'eq': [{'text': {'value': 'bar'}}]}, {'or': [{'eqnull': [{'text': {'value': 'bar2'}}]}, {'eqnull': [{'text': {'value': 'bar3'}}]}]}]}] 

這不完全是如何你想它,但你仍然可以米我希望能夠得到信息。您只需實例化一個空列表並將xml內容放入一個字符串中,然後調用一次findMarkup(xml_in_string,empty_list),該列表將被填充。

請注意,我並不真正瞭解您的最終目的,因此簡單的複製粘貼可能不夠,也許您應該優化創建inner_value的部分... 此外,此代碼假定文件完美編寫,如果需要,您應該添加異常處理。

+0

它看起來不錯!當然,我不明白這段代碼的一半(因爲我缺乏Python knowlagde),但我可以使用Google輕鬆理解它。當你悲傷時,輸出不像我喜歡的那樣,但我認爲它可以很容易地修復。不幸的是,我的團隊決定放棄XML並轉向另一個方向,所以我無法在現實生活中測試您的解決方案。也許有一天(當我有空閒的時候)。感謝幫助! –