2014-10-30 2 views
1

나는 다음과 같은 XML을 가지고있다. highlight 태그는 텍스트 태그보다 1 단계 아래에 있음을 유의하십시오. 조건은 다음과 같습니다.순회 이상 XML, LXML

  1. 모든 단락에 대해 추가 공간을 추가하십시오.
  2. highlight 태그의 부모를 반복하는 동안 중단 태그가 발견되면 공백을 추가하십시오.
  3. 추출 텍스트 만 내가했던 무엇 highlight 태그

에 해당하는 것은 :

text=""        #initialize an empty string 
for p in lxml_tree.findall('para'): #itertate over each paragraph (all paragarpahs have the same tag name para) 
    for r in p.findall("Run"):  #iterate over each run 
     for a in r.iter(tag="highlight"): #search for highlight tag 
      for b in a.iterancestors(): #go back to the parents 
       if b.tag=="break":  #if break found 
        text+=" "   # add a space 
       elif b.tag=="text": # if text found 
        text+=''.join(b.text) #add text 

위 iterancestors는 루트 노드에있는 모든 방법을 이동할 때 작동하지 않습니다. 부모님을 어떻게 반복 할 수 있습니까? 즉 Runprop, breaktext ?? 나는 모든 텍스트이 비슷한을 구현하고 그 일을 ..

편집 1 : 그냥 결함 로직 위
, 나는 오히려 break 첫째, 다음 검색, 단락의 각 Run 반복 것 Runprop 내에 강조 표시가 있는지 확인한 다음 부모 형제의 텍스트를 추출합니다.

+0

오타가 있거나 'highlight'에 닫는 태그가 없습니까? – Anzel

+0

오, 잠깐만 기다려주십시오, 자기 마감 태그입니다 .. 고칠 것입니다. –

+0

'runprop'과'RunProp'도 역시 ... 대소 문자가 일치하지 않습니다 :) – Anzel

답변

1

:

from lxml import etree 

html = ''' 
<head> 
    <body> 
    <para> 
     <Run> 
     <RunProp> 
      <highlight val="red" /> 
     <break/> 
     <text> 
     Hello there 
     </text> 
     </RunProp> 
     </Run> 
     <Run> 
     <break/> 
     </Run> 
     <Run> 
     <text> 
      See you there 
     </text> 
     </Run> 
    </para> .. 
    </body> 
</head>''' 

tree = etree.fromstring(html) 

for node in tree.iter(): 
    if node.tag == 'para': 
     node.text = '..your space here..' + node.text 
     print node.text 
    if node.tag == 'highlight': 
     print node.values() 
     if node.getnext().tag == 'break': 
      print node.getnext().tag 
      if node.getnext().getnext().tag == 'text': 
       node.getnext().getnext().text = \ 
        '..your space here..' + node.getnext().getnext().text 
       print node.getnext().getnext().text 
     elif node.getnext().tag == 'text': 
      print node.getnext().text 

..your space here....your space here.. 

['red'] 
break 
..your space here....your space here.. 
     Hello there 

파일에 변경 사항을 작성 :

나는 당신이 필요 달성하기 위해 itergetnext를 사용하는거야 그리고 anzel의 대답으로부터 아이디어를 얻는 것.

text=""   
for p in lxml_tree.findall('para'): #iterate over paragraphs 
    text+= " "      #add spaces 
    for r in p.findall("Run"):  #iterate over each run in para 
     for a in r.findall("break"): #search for break tag in it and add space if found 
      text+= " " 
     for b in r.findall('.//highlight[@val="red"]/../..//text'): #search for red highlight in that run and return text 
      text+=''.join(b.text) # append text to main string 
+0

예'xpath'는 자신의 대답을 받아들이는 것이 행복 할 것입니다. – Anzel

+0

사실 그 findall은 xpath가 더 복잡합니다. 시간 내 줘서 고마워 . 희망을 당신도 오늘 뭔가 배웠습니다. –

+0

참고로 findall은'xpath' 구문도 사용합니다 :) – Anzel

1

xml은 <highlight>, <break /><text>과 같은 위치 패턴을 가지고 있기 때문에 실제로 부모로 돌아갈 필요가 없습니다. 몇 가지 생각 후 그것을 해결하기 위해 내가 관리해야

etree.ElementTree(tree).write('output.xml', pretty_print=True) 

cat output.xml 
<head> 
    <body> 
    <para>..your space here.. 
     <Run> 
     <RunProp> 
      <highlight val="red"/> 
     <break/> 
     <text>..your space here.. 
     Hello there 
     </text> 
     </RunProp> 
     </Run> 
     <Run> 
     <break/> 
     </Run> 
     <Run> 
     <text> 
      See you there 
     </text> 
     </Run> 
    </para> .. 
    </body> 
</head> 
+0

나는 그것을 고칠 수 있었다. .. –

+0

그래서 당신은 지금 그것을 얻는다? 멋지다. – Anzel

+0

+1, 너에게 +1 아이디어를 주었다 .. :) –