2016-04-12 33 views
-2

xmlファイルのレイアウトに基づいて特定の値を取得するのは簡単です。 (StackOverflowPython:xmltodictで作成されたすべてのネストされたキーと値のペアをループします。

しかし、私がXML要素を知らないとき、私はそれを再帰することはできません。 xmltodocはOrderedDictsでOrderedDictsをネストしているので。これらの入れ子にされたOrderedDictsは、Pythonによって型: 'unicode'としてtypingされています。 OrderedDictsではなく(まだ)。そのためには、このようにオーバールーピング、doens't仕事:

def myprint(d): 
    for k, v in d.iteritems(): 
     if isinstance(v, list): 
      myprint(v) 
     else: 
      print "Key :{0}, Value: {1}".format(k, v) 

私は基本的には欲しいが、すべてのキーと値のペアが示されている全体のxmlファイルの上に再帰することです。そして、キーの値が別のキーと値のペアのリストである場合、それはそのキーに再帰的に入ります。入力として、このXMLファイルで

<?xml version="1.0" encoding="utf-8"?> 
<session id="2934" name="Valves" docVersion="5.0.1"> 
    <docInfo> 
     <field name="Employee" isMandotory="True">Jake Roberts</field> 
     <field name="Section" isOpen="True" isMandotory="False">5</field> 
     <field name="Location" isOpen="True" isMandotory="False">Munchen</field> 
    </docInfo> 
</session> 

と上記のコードは、セッションの下のすべてのデータは、セッション鍵の値として加算されます。

出力例:

Key :session, Value: OrderedDict([(u'@id', u'2934'), (u'@name', u'Valves'), (u'@docVersion', u'5.0.1'), (u'docInfo', OrderedDict([(u'field', [OrderedDict([(u'@name', u'Employee'), (u'@isMandotory', u'True'), ('#text', u'Jake Roberts')]), OrderedDict([(u'@name', u'Section'), (u'@isOpen', u'True'), (u'@isMandotory', u'False'), ('#text', u'5')]), OrderedDict([(u'@name', u'Location'), (u'@isOpen', u'True'), (u'@isMandotory', u'False'), ('#text', u'Munchen')])])]))]) 

そして、これは私が欲しいものは明らかではありません。

+0

'else'文の字下げはforループの後にありますが、あなたが意図したものではないと思いますし、' isinstance(v、list) 'の大文字小文字を追加できないのはなぜですか? –

+0

ああ、そうです。打ち間違え。ありがとう。 – JakeRoberts

+0

xmlを解析しようとしていますか?あなたはどこに向かいますか? – securecurve

答えて

0

あなたがデータにリストに遭遇した場合、あなただけのリストのすべての要素にmyprintを呼び出す必要があります:

... 
Key :@name, Value: Employee 
Key :@isMandotory, Value: True 
Key :#text, Value: Jake Roberts 
Key :@name, Value: Section 
Key :@isOpen, Value: True 
Key :@isMandotory, Value: False 
Key :#text, Value: 5 
... 

def myprint(d): 
    if isinstance(d,dict): #check if it's a dict before using .iteritems() 
     for k, v in d.iteritems(): 
      if isinstance(v, (list,dict)): #check for either list or dict 
       myprint(v) 
      else: 
       print "Key :{0}, Value: {1}".format(k, v) 
    elif isinstance(d,list): #allow for list input too 
     for item in d: 
      myprint(item) 

その後、あなたのような出力に何かを取得します@nameのような重複したキーがたくさんあるので、これがどれほど有用かはわかりませんが、入れ子になったjsonのデータを横断するためにしばらく前に作成した関数を提供したいと思います。とlist S:あなたが書くことができますが

obj[u'session'][u'@id'] = 2934 
obj[u'session'][u'@name'] = Valves 
obj[u'session'][u'@docVersion'] = 5.0.1 
obj[u'session'][u'docInfo'][u'field'][0][u'@name'] = Employee 
obj[u'session'][u'docInfo'][u'field'][0][u'@isMandotory'] = True 
obj[u'session'][u'docInfo'][u'field'][0]['#text'] = Jake Roberts 
obj[u'session'][u'docInfo'][u'field'][1][u'@name'] = Section 
obj[u'session'][u'docInfo'][u'field'][1][u'@isOpen'] = True 
obj[u'session'][u'docInfo'][u'field'][1][u'@isMandotory'] = False 
obj[u'session'][u'docInfo'][u'field'][1]['#text'] = 5 
obj[u'session'][u'docInfo'][u'field'][2][u'@name'] = Location 
obj[u'session'][u'docInfo'][u'field'][2][u'@isOpen'] = True 
obj[u'session'][u'docInfo'][u'field'][2][u'@isMandotory'] = False 
obj[u'session'][u'docInfo'][u'field'][2]['#text'] = Munchen 

:それはこのような出力を提供しますpath_reprprev_pathのデフォルト値で

for path,value in traverse(doc): 
    print("{} = {}".format(path,value)) 

と:

def traverse(obj, prev_path = "obj", path_repr = "{}[{!r}]".format) 
    if isinstance(obj,dict): 
     it = obj.items() 
    elif isinstance(obj,list): 
     it = enumerate(obj) 
    else: 
     yield prev_path,obj 
     return 
    for k,v in it: 
     for data in traverse(v, path_repr(prev_path,k), path_repr): 
      yield data 

次にあなたがデータを通過することができますpath_reprの関数は、prev_path(再帰的にはpath_reprを呼び出すことによって決定される)の値をとる関数と、

def add_to_tuple(prev,new): 
    return prev+(new,) #prev is a tuple, add in the new element to the tuple 

for path,value in traverse(doc,(),add_to_tuple): #prev_path is initially an empty tuple 
    print("{} = {}".format(path,value)) 

、出力は次のようになります:あなたはこれを行うことがタプルとしてインデックスを取得したい場合、たとえば、新しいキー、私のJSONを扱うとき

... 
(u'session', u'docInfo', u'field', 0, '#text') = Jake Roberts 
(u'session', u'docInfo', u'field', 1, u'@name') = Section 
(u'session', u'docInfo', u'field', 1, u'@isOpen') = True 
(u'session', u'docInfo', u'field', 1, u'@isMandotory') = False 
(u'session', u'docInfo', u'field', 1, '#text') = 5 
... 

は、私は、これは特に有用であることが判明しましたデータはありますが、XMLで何をしたいのか分かりません。

+0

うわー。それは超です!魅力のように動作します。特にトラバース機能!どうもありがとうございました! – JakeRoberts

関連する問題