2011-05-04 5 views
2

추가 구문 분석을 위해 포함 된 템플릿 태그를 추출하려면 XML을 구문 분석해야합니다. 파이썬의 정규식을 구부려서 내가 원하는 것을 할 수는 없다.XML의 템플릿 태그를 구문 분석하는 정규 표현식

영어 : 서식 파일 태그가 행의 모든 ​​위치에 포함되어 있으면 해당 특정 행에 대한 모든 XML을 제거하고 템플릿 태그 만 그대로 둡니다.

설명을 위해 테스트 사례를 정리했습니다.

<!-- regex_trial.xml --> 
<w:tbl> 
    <w:tr> 
     <w:tc><w:t>Header 1</w:t></w:tc> 
     <w:tc><w:t>Header 2</w:t></w:tc> 
     <w:tc><w:t>Header 3</w:t></w:tc> 
    </w:tr> 
    <w:tr> 
     <w:tc><w:t>{% for i in items %}</w:t></w:tc> 
     <w:tc><w:t></w:t></w:tc> 
     <w:tc><w:t></w:t></w:tc> 
    </w:tr> 
    <w:tr> 
     <w:tc><w:t>{{ i.field1 }}</w:t></w:tc> 
     <w:tc><w:t>{{ i.field2 }}</w:t></w:tc> 
     <w:tc><w:t>{{ i.field3 }}</w:t></w:tc> 
    </w:tr> 
    <w:tr> 
     <w:tc><w:t>{% endfor %}</w:t></w:tc> 
     <w:tc><w:t></w:t></w:tc> 
     <w:tc><w:t></w:t></w:tc> 
    </w:tr> 
</w:tbl> 

이는 원하는 결과 :

#!/usr/bin/env python 
import re 
f = open('regex_trial.xml', 'r') 
orig_xml = f.read() 
f.close() 
p = re.compile('<w:tr.*?(?P<tag>{%.*?%}).*?</w:tr>', re.DOTALL) 
new_xml = p.sub('\g<tag>', orig_xml, 0) 
print new_xml 

실제 결과 : 여기

<!-- regex_desired_result.xml --> 
<w:tbl> 
    <w:tr> 
     <w:tc><w:t>Header 1</w:t></w:tc> 
     <w:tc><w:t>Header 2</w:t></w:tc> 
     <w:tc><w:t>Header 3</w:t></w:tc> 
    </w:tr> 
    {% for i in items %} 
    <w:tr> 
     <w:tc><w:t>{{ i.field1 }}</w:t></w:tc> 
     <w:tc><w:t>{{ i.field2 }}</w:t></w:tc> 
     <w:tc><w:t>{{ i.field3 }}</w:t></w:tc> 
    </w:tr> 
    {% endfor %} 
</w:tbl> 

내가 테스트에 사용하고 일부 파이썬 코드 여기에 원래의 XML입니다 이 정규식의 :

<!-- regex_trial.xml --> 
<w:tbl> 
    {% for i in items %} 
    {% endfor %} 
</w:tbl> 

도움을 주시면 대단히 감사하겠습니다. 이것을 파악할 수 있다면 Django 기반 사이트에서 MS Word docx 파일을 동적으로 생성 할 수 있습니다. 감사!!

업데이트 :이 나는

from xml.etree import ElementTree 
import cStringIO as StringIO 

TEMPLATE_TAG = 'template_text' 

tree = ElementTree.parse('regex_trial.xml') 
rows = tree.getiterator('tr') 
for row in rows: 
    for cell in row.getiterator('t'): 
     if cell.text and cell.text.find('{%') >= 0: 
      template_tag = cell.text 
      row.clear() 
      row.tag = TEMPLATE_TAG 
      row.text = template_tag 
      break 

output = StringIO.StringIO() 
tree.write(output) 
xml = output.getvalue() 
xml = xml.replace('<%s>' % TEMPLATE_TAG, '') 
xml = xml.replace('</%s>' % TEMPLATE_TAG, '') 
print xml 

모든 도움을 주셔서 감사를 최종 코드 사용되는!

+2

@ user425130 XML/XSLT 파서를 사용 해본 적이 있습니까? –

+0

내가 XSL을 고려해 봤지만, 꽤 못 생겼다. 각 tr을 검사해야한다. tc의 내용을 검사하는 xpath 표현식이 필요하다. 그런 다음 우리가 만지기를 원하지 않는 다른 99 %의 콘텐츠를 처리해야합니다. 응. – aeb6

+0

@ user425130 +1 큰 해결책!Bravo –

답변

4

이 문제는 정규식을 사용하지 마십시오.

저는 정규 표현식으로 XML을 파싱하는 것이 어렵다는 것을 알고, 다른 사람이 코드를 50 배 덜 유지할 수 있도록합니다.

lxml은 Pythonist가 XML을 구문 분석하는 데 사용하는 도구입니다. 예제 사용을 위해 this article on Stack Overflow을보십시오. 또는 this answer을 생각해보십시오. 어느 이어야합니다.이 답변으로 받아 들여졌습니다.

빠른 데모로 해킹했습니다. <w:tc>이 비어 있지 않고 <w:t> 어린이를 검색하고 각 요소 옆에 잘 인쇄됩니다.

import lxml.etree as ET 
from lxml.etree import XMLParser 

def worthy(elem): 
    for child in elem.iterchildren(): 
     if (child.tag == 't') and (child.text is not None): 
      return True 
    return False 

def dump(elem): 
    for child in elem.iterchildren(): 
     print "Good", child.tag, child.text 

parser = XMLParser(ns_clean=True, recover=True) 
etree = ET.parse('regex_trial.xml', parser) 
for thing in etree.findall("//"): 
    if thing.tag == 'tc' and worthy(thing): 
     dump(thing) 

수익률 ...

Good t Header 1 
Good t Header 2 
Good t Header 3 
Good t {% for i in items %} 
Good t {{ i.field1 }} 
Good t {{ i.field2 }} 
Good t {{ i.field3 }} 
Good t {% endfor %} 
+0

+1 :'xml.etree.ElementTree'는 표준 라이브러리에 머무르기를 원한다면 적당한 선택입니다. – jathanism

+0

@jathanism 그것을 지적 해 주셔서 고맙습니다. 나는 항상'lxml'을 사용했습니다. –

+0

XML 라이브러리에서 이것을 어떻게 할 것인가에 대한 제안은 무엇입니까? 모든 노드를 검사하여 "{% * %}"이 (가) 포함 된 노드가 있는지 확인한 다음 을 자식 노드의 내용으로 바꿔야합니다. 복잡해지기 시작합니다. 또한 필자는 문서 나머지 부분 (99 % 이상)을 그대로 두어야 할 필요가 있으므로 찾기/바꾸기 경로를 사용하고 있습니다. 모든 예제가 도움이 될 것입니다. 감사! – aeb6

3

결코 이제까지 구문 분석 HTML 또는 정규 표현식 XML 또는 SGML.

항상 lxml, libxml2 또는 Beautiful와 같은 도구를 사용하십시오. 코드보다 더 똑똑하고 더 좋은 작업을 수행 할 것입니다.