用于解析 XML 中模板标签的正则表达式
我需要解析一些 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>
非常感谢任何帮助!如果我们能弄清楚这一点,我们将能够从 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
感谢您的所有帮助!
I need to parse some XML to pull out embedded template tags for further parsing. I can't seem to bend Python's regular expressions to do what I want, though.
In English: when a template tag is contained anywhere in the row, remove all the XML for that specific row and leave only the template tag in its place.
I put together a test case to demonstrate. Here's the original 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>
This is the desired result:
<!-- 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>
Here is some python code I am using to test:
#!/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
The actual result of this regex is:
<!-- regex_trial.xml -->
<w:tbl>
{% for i in items %}
{% endfor %}
</w:tbl>
Any help is greatly appreciated! If we can figure this out, we will be able to dynamically generate MS Word docx files on the fly from Django-powered sites. Thanks!!
Update: this is the final code that I used
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
Thanks for all the help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
请不要使用正则表达式来解决此问题。
我是认真的,使用正则表达式解析 XML 很困难,而且它会使您的代码对其他人的可维护性降低 50 倍。
lxml 是 pythonista 用来解析 XML 的事实上的工具...看看 这篇关于 Stack Overflow 的文章用于示例使用。或者考虑这个答案,应该是被接受的答案。
我将其破解为一个快速演示...它搜索带有非空
子项的
并在旁边打印 good每个元素。产量...
Please don't use regular expressions for this problem.
I'm serious, parsing XML with a regex is hard, and it makes your code 50x less maintainable by anyone else.
lxml is the defacto tool that pythonistas use to parse XML... take a look at this article on Stack Overflow for sample usage. Or consider this answer, which should have been the answer that was accepted.
I hacked this up as a quick demo... it searches for
<w:tc>
with non-empty<w:t>
children and prints good next to each element.Yields...
永远不要使用正则表达式解析 HTML 或 XML 或 SGML。
始终使用 lxml、libxml2 或 Beautiful 等工具 - 它们会做得更聪明、更好
工作比你的代码。
Never ever parse HTML or XML or SGML with regular expressions.
Always use tools like lxml, libxml2 or Beautiful - they will ever do a smarter and better
job than your code .