Python 3.x 按元素将包含多条记录和无效字符的XML文件拆分为多个文本文件
我有一组具有一致结构的100K XML ish(稍后将详细介绍)遗留文件—一个包含多个日期和数据对记录的归档包装器 我需要提取单个记录并将其写入单个文本文件,但由于非法字符和随机的CR/space/tab前导和尾随数据,我在解析数据时遇到了问题 关于XML文件 这些文件是从失效系统继承的,无法重新生成。每个文件都非常小(小于5MB) 每个数据记录都有一个日期记录:Python 3.x 按元素将包含多条记录和无效字符的XML文件拆分为多个文本文件,python-3.x,xml-parsing,Python 3.x,Xml Parsing,我有一组具有一致结构的100K XML ish(稍后将详细介绍)遗留文件—一个包含多个日期和数据对记录的归档包装器 我需要提取单个记录并将其写入单个文本文件,但由于非法字符和随机的CR/space/tab前导和尾随数据,我在解析数据时遇到了问题 关于XML文件 这些文件是从失效系统继承的,无法重新生成。每个文件都非常小(小于5MB) 每个数据记录都有一个日期记录: vendor-1-records.xml <Archive> <Date>10 Jan 2019</
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>
问题1:XML数据记录中的非法字符
一个问题是,元素包含多个XML库(如Etree/etc)终止的字符,包括控制字符、格式字符和各种Alt+XXX类型的字符
我在网上搜索过,找到了各种各样的变通方法和regex,以及搜索和替换脚本,但在Python中唯一有效的是lxml的etree,recover=True
但是,这并不总是有效的,因为有些文件显然不是UTF-8,所以我得到了错误:
lxml.etree.XMLSyntaxError: Input is not proper UTF-8, indicate encoding !
问题2-数据记录具有随机数量的前导和后继CR和空格
对于我可以用lxml.etree解析的文件,实际数据记录也包装在CRs和随机空间中:
<Data>
(random numbers of CR + spaces and sometimes tabs)
*content<CR>*
(random numbers of CR + spaces and sometimes tabs)
</Data>
我得到一组空数据标记(文件中的每个数据记录对应一个),如
问题
对于我的问题1和2,我解决了我自己的问题:
- 问题1(解析和无效字符)
- 我使用批处理脚本通过()中引用的Atlassian jar运行了整个文件集:
- 问题2(数据元素内的CR、空格、选项卡)
- lxml的此配置去除了所有空白,并处理了无效字符问题
# 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()
在这里,作为文本进行解析,也许之后作为XML进行解析是有意义的。例如您提到的atlassion XML清理器。或者拥有自己的代码,这样您就可以逐步解决编码错误、非法字符、空白等问题。
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 {}
for %%f in (*.xml) do (
java -jar atlassian-xml-cleaner-0.1.jar %%f > clean\%%~f
)
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()