2009-03-27 5 views
1

XML 파일을 구문 분석하고 데이터에서 레코드 기반 출력을 작성해야합니다. 문제는 XML이 일종의 데이터 구조를 나타내는 여러 수준의 중첩 된 "노드"요소를 가지고 있으므로 "일반"형식이라는 것입니다. "노드"요소의 가장 깊은 수준을 기반으로 동적으로 레코드를 작성해야합니다. XML 및 예상 출력의 예가 맨 아래에 있습니다.Python XML - 동적 중첩 "노드"요소에서 플랫 레코드 만들기

저는 파이썬의 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

있다고. 당신이 XML 문서를 준 누구든지

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 

편집 다른 직업을 찾을 필요가있다. 이것은 잘못된 것 (TM)이며 XML이 의미하는 바를 간과하게 무시합니다.

+0

빠른 응답을 주셔서 감사합니다. 노드 이름은 모두 "노드"이며 불행히도 앞서 언급했듯이 "하위 그룹"이 마지막 레벨이라고 가정 할 수 없습니다. 그렇지 않으면 매우 쉽습니다. 노드 깊이는 정적이지 않습니다. 하위 그룹 "노드"의 하위 항목이있을 수 있습니다. 생각? 다시 한 번 감사드립니다! – John

+0

또한 각 "레벨"에는 여러 하위 수준이있을 수 있습니다. 따라서 최상위 노드 루프에서 단일 객체를 만드는 것은 작동하지 않습니다. 각 자식 "노드"를 반복해야 각 레코드를 작성할 수 있습니다. – John

+0

@ S.Lott - XML ​​구조에 대해서는 더 이상 동의 할 수 없지만 불행히도 "시스템 생성"이며 변경을 거부합니다. :-( – John

0

나는 ElementTree 모듈에 익숙하지 않지만 요소에 getchildren() 메서드를 사용할 수 있어야하며 더 이상 자식이 없을 때까지 데이터를 반복적으로 파싱해야합니다. 이것은 무엇보다도 sudo 코드입니다 :

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