2014-04-17 4 views
1

구문 분석하려고하는 XML이 있습니다. 예 :Python/lxml : for 중첩 된 루프

<TVAMain> 
    <ProgramDescription> 
     <ProgramLocationTable> 
      <Schedule value1="1234"> 
       <ScheduleEvent> 
        <Program value2="1234567890" /> 
       </ScheduleEvent> 
       <ScheduleEvent> 
        <Program value2="1234567891" /> 
       </ScheduleEvent> 
      </Schedule> 
      <Schedule value1="5678"> 
       <ScheduleEvent> 
        <Program value2="1234567892" /> 
       </ScheduleEvent> 
       <ScheduleEvent> 
        <Program value2="1234567893" /> 
       </ScheduleEvent> 
      </Schedule> 
     </ProgramLocationTable> 
    </ProgramDescription> 
</TVAMain> 

내가 값 1로 파일에 값 1의 모든 항목 및 값 2의 모든 항목 및 출력을 검색하려고 | 값 2를. 나는 성공적으로 값 1 또는 값 2를 파일에 쓰도록 할 수 있지만 동시에 얻을 수는 없습니다! 이것은 지금까지 내 코드입니다

(나는 시간 인을위한 쓰기 단계를 도랑을했습니다, 그냥 첫 번째 데이터의 두 비트를 출력하는 데려고) :

from lxml import etree 

parser = lxml.etree.XMLParser() 


tree = lxml.etree.parse(file_name, parser) 
root = tree.getroot() 

nsmap = {'xmlns': 'urn:tva:metadata:2010'} 

with codecs.open(file_name+'.log', mode='w', encoding='utf-8') as f: 
    for info in root.xpath('//xmlns:Schedule', namespaces=nsmap): 
     value1 = (info.get('value1')) 
     print (serviceid) 
     for info in root.xpath('//xmlns:Schedule[@value1 = "value1"]/ScheduleEvent/Program', namespaces=nsmap): 
       value2 = (info.get('value2')) 
       print (crid) 

이 코드 것이다 성공적으로 인쇄 모든 'value1'값은 있지만 value2는 없습니다.

나는 시도 다음 - 루프 에 대한 두 번째의 '정보 2'를 사용 - 두 번째 XPath는 함께 장난, 값 1

알려진 값을 입력 이

사람이 올바른 방향으로 날 지점 수 있습니까? 당신이 게시 된 XML 작업

+0

네를, 죄송합니다. 오타되었습니다. – Nick

답변

1

, 하나의 XPath 모든 값을 찾을 수 :이 XPath는이 가정

import lxml.etree as ET 

tree = ET.parse('data') 
tree.xpath('//Schedule') 

values = tree.xpath('//Schedule/@value1 | //Schedule/ScheduleEvent/Program/@value2') 
for vals in zip(*[iter(values)]*3): 
    print(vals) 

인쇄

('1234', '1234567890', '1234567891') 
('5678', '1234567892', '1234567893') 

value2 속성 다음에 하나 개 value1 속성은 항상있다 . 코드에서

for schedule in tree.xpath('//Schedule[@value1]'): 
    value1 = schedule.get('value1') 
    print(value1) 
    for value2 in schedule.xpath('ScheduleEvent/Program/@value2'): 
     print(value2) 

: 당신이 그 가정에 의존하지 않으려는 경우에 당신은 루프이 방법을 대신 할 수

root.xpath('//xmlns:Schedule[@value1 = "value1"]/ScheduleEvent/Program', namespaces=nsmap) 
"value1"는 리터럴 문자열이기 때문에

작동하지 않았다 . 당신은 변수 value1와 그 대체해야합니다 :

'//xmlns:Schedule[@value1 = "{v}"]/ScheduleEvent/Program'.format(v=value1) 

가 작동 할 때 있지만, 당신이 필요로하는 것보다 더 많은 특정 될 수있는 value1를 지정. 또는 두 개의 Schedule 요소가 동일한 value1 특성을 가질 경우 충분하지 않을 수 있습니다. 대신 schedule.xpath를 호출하여 어린이들에게 Program 요소를 찾을 수 있습니다

schedule.xpath('ScheduleEvent/Program/@value2') 

을 대신 tree.xpath를 사용하여 트리의 상단부터 시작하는.

+0

깔끔한 솔루션처럼 보이지만, 내가 원하는 것을 나에게주지는 않습니다. 엑셀로 가져올 때 조작하기 쉽도록 각각의 'value2'를 별도의 줄로 가져 오려고합니다. 위의 ebarr 솔루션을 살펴보고 작동하도록 노력하겠습니다.어쨌든 고마워요. 나중에 생각하면 유용 할 것입니다! – Nick

+0

그루퍼 제조법 인'zip (* [iter (values)] * 3)'을 원하지 않는다면 사용하지 않아도됩니다. 그냥'values'를 출력하십시오. – unutbu

0

lxml를 사용하는 다른 방법은 다음과 같습니다이 인쇄됩니다

import lxml.etree as et 

message = """<?xml version="1.0" encoding="UTF-8"?>  
<TVAMain>             
    <ProgramDescription>         
     <ProgramLocationTable>        
      <Schedule value1="1234">      
       <ScheduleEvent>       
        <Program value2="1234567890" />  
       </ScheduleEvent>       
       <ScheduleEvent>       
        <Program value2="1234567891" />  
       </ScheduleEvent>       
      </Schedule>         
      <Schedule value1="5678">      
       <ScheduleEvent>       
        <Program value2="1234567892" />  
       </ScheduleEvent>       
       <ScheduleEvent>       
        <Program value2="1234567893" />  
       </ScheduleEvent>       
      </Schedule>         
     </ProgramLocationTable>       
    </ProgramDescription>         
</TVAMain>""" 

tree = et.fromstring(message) 
schedules = tree.xpath("ProgramDescription/ProgramLocationTable")[0].findall("Schedule") 
for schedule in schedules: 
    for event in schedule.findall("ScheduleEvent"): 
     program = event.find("Program") 
     print schedule.attrib["value1"],program.attrib["value2"] 

:

1234 1234567890 
1234 1234567891 
5678 1234567892 
5678 1234567893 
+0

schedules = tree.find ("ProgramLocationTable") findall ("Schedule") AttributeError : 'NoneType'객체에 'findall'속성이 없습니다. XML에 확실히 존재합니다. 어떤 아이디어? – Nick

+0

아마도'tree.find ("ProgramLocationTable")'이'None'을 리턴하고 있음을 의미합니다. 사용하는 XML이 게시 한 XML과 다른가요? 나는 당신의 모범을 가지고 시험해 보았고 이것은 잘 작동합니다. – ebarr

+0

XML 구조가 일치하지 않습니다. 나는 최상위 레벨 태그 'TVAMain'을 생략했다. 나는 테스트를했고, 이것을 샘플에 추가하면 위에 게시 한 파일이 손상됩니다. 왜 이런거야? ProgramLocationTable이 최상위 레벨에 없기 때문에 작동하지 않는 이유는 무엇입니까? – Nick