如何解决按元素
我有一组100K XML格式(稍后会详细介绍)的旧文件,它们具有一致的结构-带有多个日期和数据对记录的存档包装。
我需要提取单个记录并将它们写入单个文本文件,但是由于非法字符以及随机的CR /空格/制表符前导和尾随数据,在解析数据时遇到了麻烦。
关于XML文件
文件是从淘汰的系统继承的,无法重新生成。每个文件都非常小(不到5 MB)。
每个数据记录都有一个日期记录:
vendor-1-records.xml
<Archive>
<Date>10 Jan 2019</Date>
<Data>Vendor 1 Record 1</Data>
<Date>12 Jan 2019</Date>
<Data>Vendor 1 Record 2</Data>
(etc)
</Archive>
vendor-2-records.xml
<Archive>
<Date>22 September 2019</Date>
<Data>Vendor 2 Record 1</Data>
<Date>24 September 2019</Date>
<Data>Vendor 2 Record 2</Data>
(etc)
</Archive>
...
vendor-100000-records.xml
<Archive>
<Date>12 April 2019</Date>
<Data>Vendor 100000 Record 1</Data>
<Date>24 October 2019</Date>
<Data>Vendor 100000 Record 2</Data>
(etc)
</Archive>
我想提取每个数据记录并使用Date条目定义一个唯一的文件名,然后将Data记录的内容这样写到该文件中
filename: vendor-1-record-1-2019-1Jan-10.txt contains
file contents: Vendor 1 record 1
(no tags,just the record terminated by CR)
filename: vendor-1-record-2-2019-1Jan-12.txt contains
file contents: Vendor 1 record 2
filename: vendor-2-record-1-2019-9Sep-22.txt contains
file contents: Vendor 2 record 1
filename: vendor-2-record-2-2019-9Sep-24.txt contains
file contents: Vendor 2 record 2
问题1:XML数据记录中的非法字符
一个问题是元素包含XML库(例如Etree / etc)终止的多个字符,包括控制字符,格式设置字符和各种Alt + XXX类型的字符。
我已经在线搜索了,找到了各种解决方法,正则表达式以及搜索和替换脚本的方法,但是似乎唯一适用于Python的方法是lxml的etree带有restore = True。
但是,由于某些文件显然不是UTF-8,所以这甚至不总是有效,所以我得到了错误:
lxml.etree.XMLSyntaxError: Input is not proper UTF-8,indicate encoding !
问题2-数据记录具有随机数量的前导和后继CR和空格
对于我可以使用lxml.etree解析的文件,实际的数据记录也包装在CR和随机空间中:
<Data>
(random numbers of CR + spaces and sometimes tabs)
*content<CR>*
(random numbers of CR + spaces and sometimes tabs)
</Data>
因此,当我跑步
parser = etree.XMLParser(recover=True)
tree = etree.parse('vendor-1-records.xml',parser=parser)
tags_needed = tree.iter('Data')
for it in tags_needed:
print (it.tag,it.attrib)
我得到了一个空数据标签的集合(文件中的每个数据记录一个),如
Data {}
Data {}
问题
- 是否有比Python的lxml更有效的语言/模块来忽略非法字符?正如我说的,我已经浏览了许多食谱博客文章,SE文章等内容,以对XML进行预处理,但是似乎没有真正起作用的地方–总是有一个控制字符/ etc挂在解析器上。
SE建议发表有关清理XML的帖子,其中引用了旧的Atlassian工具(Stripping Invalid XML characters in Java)。我做了一些基本的测试,看来它可能有用,但可以接受其他建议。
- 我没有在python上使用正则表达式-关于如何处理Data标记中的前导/尾随CR /空格/制表符随机性的任何建议?我想要在该Data标记中的实际记录字符串的末尾也有一个CR,并且可能还包含制表符,所以我不能只是搜索和替换。也许有一种正则表达式可以消除这种情况,但是我的正则表达式非常薄弱。
解决方法
对于问题1和2,我有点解决了自己的问题:
- 问题1(解析和无效字符)
- 我使用批处理脚本通过(Stripping Invalid XML characters in Java)引用的Atlassian jar运行了整个文件集:
for %%f in (*.xml) do (
java -jar atlassian-xml-cleaner-0.1.jar %%f > clean\%%~f
)
该实用程序对所有XML文件进行了标准化,并使其可被lxml解析。
- 问题2(数据元素内的CR,空格,制表符)
- 此用于lxml的配置去除了所有空白并处理了无效字符问题
from lxml import etree
parser = etree.XMLParser(encoding = 'utf-8',recover=True,remove_blank_text=True)
tree = etree.parse(filepath,parser=parser)
通过这两个步骤,我现在可以开始提取记录并将它们写入单个文件:
# for each date,finding the next item gives me the Data element and I can strip the tab/CR/whitespace:
for item in tree.findall('Date'):
dt = parse_datestamp(item.text.strip())
content = item.getnext().text.strip()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。