2009-03-27 28 views
1

XMLファイルを解析し、データからレコードベースの出力を構築する必要があります。問題は、XMLがある種のデータ構造を表すいくつかのレベルのネストされた「ノード」要素を持つという点で、XMLが「汎用」形式であることです。私はレコードを "ノード"要素の最も深いレベルに基づいて動的に構築する必要があります。 XMLと期待される出力の例が一番下にあります。Python XML - 動的なネストされた「ノード」要素からフラットレコードを作成する

私はPythonのElementTreeに最も慣れているので、それを使用したいと思いますが、ダイナミックノードの深さに基づいて出力レコードを動的に構築する方法で私の頭を包むことはできません。また、ネストされたノードがxレベルの深さになるとは仮定できません。したがって、ループごとに各レベルをハードコーディングすることはできません。 XMLを解析し、その場で出力を構築する方法はありますか?

いくつかの追加の注意事項:

  • ノード名は、すべての親と詳細情報(率、価格、など)
  • ノードの深さは静的ではありませんを除いて「ノード」です。したがって、サンプルに表示されているレベルよりもさらに高いレベルを仮定します。
  • 各 "レベル"は複数のサブレベルを持つことができます。したがって、各レコードを適切に構築するには、各子「ノード」にループする必要があります。

どのようなアイデアや入力をいただければ幸いです。

<root> 
    <node>101 
     <node>A 
     <node>PlanA  
      <node>default 
       <rate>100.00</rate> 
      </node> 
      <node>alternative 
       <rate>90.00</rate> 
      </node> 
     </node> 
     </node> 
    </node> 
    <node>102 
     <node>B 
     <node>PlanZZ  
      <node>Group 1 
       <node>default 
        <rate>100.00</rate> 
       </node> 
       <node>alternative 
        <rate>90.00</rate> 
       </node> 
      </node> 
      <node>Group 2 
       <node>Suba 
        <node>default 
         <rate>1.00</rate> 
        </node> 
         <node>alternative 
         <rate>88.00</rate> 
        </node> 
       </node> 
       <node>Subb 
        <node>default 
         <rate>200.00</rate> 
        </node> 
         <node>alternative 
         <rate>4.00</rate> 
        </node> 
       </node> 
      </node> 
     </node> 
     </node> 
    </node> 
</root> 

出力は次のようになります。あなたは、XPathを持つ要素ツリーfind方法を持っている理由

SRV SUB PLAN Group SubGrp DefRate AltRate 
101 A PlanA     100  90 
102 B PlanB Group1   100  90 
102 B PlanB Group2 Suba 1   88 
102 B PlanB Group2 Subb 200  4 

答えて

4

だこと。

class Plan(object): 
    def __init__(self): 
     self.srv= None 
     self.sub= None 
     self.plan= None 
     self.group= None 
     self.subgroup= None 
     self.defrate= None 
     self.altrate= None 
    def initFrom(self, other): 
     self.srv= other.srv 
     self.sub= other.sub 
     self.plan= other.plan 
     self.group= other.group 
     self.subgroup= other.subgroup 
    def __str__(self): 
     return "%s %s %s %s %s %s %s" % (
      self.srv, self.sub, self.plan, self.group, self.subgroup, 
      self.defrate, self.altrate) 

def setRates(obj, aSearch): 
    for rate in aSearch: 
     if rate.text.strip() == "default": 
      obj.defrate= rate.find("rate").text.strip() 
     elif rate.text.strip() == "alternative": 
      obj.altrate= rate.find("rate").text.strip() 
     else: 
      raise Exception("Unexpected Structure") 

def planIter(doc): 
    for topNode in doc.findall("node"): 
     obj= Plan() 
     obj.srv= topNode.text.strip() 
     subNode= topNode.find("node") 
     obj.sub= subNode.text.strip() 
     planNode= topNode.find("node/node") 
     obj.plan= planNode.text.strip() 
     l3= topNode.find("node/node/node") 
     if l3.text.strip() in ("default", "alternative"): 
      setRates(obj, topNode.findall("node/node/node")) 
      yield obj 
     else: 
      for group in topNode.findall("node/node/node"): 
       grpObj= Plan() 
       grpObj.initFrom(obj) 
       grpObj.group= group.text.strip() 
       l4= group.find("node") 
       if l4.text.strip() in ("default", "alternative"): 
        setRates(grpObj, group.findall("node")) 
        yield grpObj 
       else: 
        for subgroup in group.findall("node"): 
         subgrpObj= Plan() 
         subgrpObj.initFrom(grpObj) 
         subgrpObj.subgroup= subgroup.text.strip() 
         setRates(subgrpObj, subgroup.findall("node")) 
         yield subgrpObj 

import xml.etree.ElementTree as xml 
doc = xml.XML(doc) 

for plan in planIter(doc): 
    print plan 

編集

誰でもあなたにこのXMLドキュメントを与えたことは別の仕事を見つける必要があります。これはバッド・シング(TM)であり、XMLが意味することをかなり軽視していることを示しています。

+0

お返事ありがとうございます。ノード名はすべて「ノード」であり、前に述べたように残念なことに「サブグループ」が最後のレベルであるとは思いません。そうでないと非常に簡単です。ノードの深さは静的ではありません。サブグループ「ノード」の子が存在する可能性があります。思考?再度、感謝します! – John

+0

また、各 "レベル"は複数のサブレベルを持つことができます。したがって、トップノードのループからただ一つのオブジェクトを作成することはできません。それぞれの子「ノード」もループして各レコードを構築する必要があります。 – John

+0

@ S.Lott - 私はXML構造についてもっとは同意できませんでしたが、残念ながら "システム生成"であり、変更を拒否しています。 :-( – John

0

私はElementTreeモジュールにあまり慣れていませんが、要素にgetchildren()メソッドを使用できるようにして、子がなくなるまで再帰的に解析します。これは何よりもsudo-codeです:

def parseXml(root, data): 
    # INSERT CODE to populate your data object here with the values 
    # you want from this node 
    sub_nodes = root.getchildren() 
    for node in sub_nodes: 
     parseXml(node, data) 

data = {} # I'm guessing you want a dict of some sort here to store the data you parse 
parseXml(parse(file).getroot(), data) 
# data will be filled and ready to use 
関連する問題