Регулярные выражения для разбора тегов шаблона в XML - PullRequest
2 голосов
/ 04 мая 2011

Мне нужно проанализировать некоторые XML, чтобы извлечь встроенные теги шаблона для дальнейшего анализа.Однако я не могу сгибать регулярные выражения Python, чтобы делать то, что я хочу.

На английском языке: когда тег шаблона содержится в любом месте строки, удалите все 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>

Это желаемый результат:

<!-- 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>

Вот код Python, который я использую для проверки:

#!/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_trial.xml -->
<w:tbl>
    {% for i in items %}
    {% endfor %}
</w:tbl>

Любая помощь очень ценится!Если мы сможем это выяснить, мы сможем динамически генерировать docx-файлы MS Word на лету с сайтов, работающих на Django.Спасибо !!

Обновление: это последний код, который я использовал

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 ]

4 голосов
/ 04 мая 2011

Пожалуйста, не используйте регулярные выражения для этой проблемы.

Я серьезно, синтаксический анализ XML с помощью регулярных выражений труден, и он делает ваш код в 50 раз менее понятным для других пользователей.

lxml - это инструмент де-факто, который pythonistas использует для анализа XML ... взгляните на эту статью о переполнении стека для примера использования. Или рассмотрите этот ответ , который должен быть тем ответом, который был принят.

Я взломал это как короткую демонстрацию ... он ищет <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 %}
3 голосов
/ 04 мая 2011

Никогда не анализирует HTML, XML или SGML с помощью регулярных выражений.

Всегда используйте такие инструменты, как lxml, libxml2 или Beautiful - они будут работать умнее и лучше, чем ваш код.

...