我需要解析 xml 数据的帮助。场景如下:
- 我有 xml 文件作为字符串加载到 postgresql 数据库中。
- 我将它们下载到文本文件中以供进一步分析。每行对应一个 xml 文件。
- 字符串具有不同的编码。有些明确指定utf-8,有些则指定 windows-1252。可能还有其他人;有些没有在字符串中指定编码。
- 我需要解析这些字符串以获取数据。我发现的最佳方法如下:
encoded_string = bytes(bytearray(xml_data, encoding='utf-8'))
root = etree.fromstring(encoded_string)
当它不起作用时,我收到两种类型的错误消息:
"Extra content at the end of the document, line 1, column x (<string>, line 1)"
# x varies with string; I think it corresponds to the last character in the line
查看引发异常的行,看起来额外内容错误是由具有windows-1252编码的文件引发的。
我需要能够解析每个字符串,理想情况下,下载后不必以任何方式更改它们。我尝试了以下方法:
- 改为应用"windows-1252"作为编码。 以
- 二进制形式读取字符串,然后应用编码
- 将字符串读取为二进制并使用
etree.fromstring
直接转换
最后一次尝试产生了此错误:ValueError: Unicode strings with encoding declaration are not supported. Please use bytes input or XML fragments without declaration.
我能做什么?我需要能够读取这些字符串,但无法弄清楚如何解析它们。带有窗口编码的 xml 字符串都以<?xml version="1.0" encoding="windows-1252" ?>
开头
鉴于表列是文本,所有 XML 内容都以 UTF-8 格式呈现给 python,因此尝试解析冲突的 XML 编码属性会导致问题。
也许尝试从字符串中删除该属性。
我通过删除编码信息、换行符文字和回车符文字来解决这个问题。如果我在 vim 中打开返回错误的文件并运行以下三个命令,则每个字符串都成功解析:
:%s/\r//g
:%s/\n//g
:%s/<?.*?>//g
然后 lxml 解析了字符串而没有问题。
更新:
我有一个更好的解决方案。问题是 和 \r 文本中的 UTF-8 编码字符串我正在复制到文本文件。我只需要用这样的regexp_replace
从字符串中删除这些字符:
select regexp_replace(xmlcolumn, '\n|\r', '', 'g') from table;
现在我可以运行以下命令并使用 lxml 读取数据而无需进一步处理:
psql -d database -c "copy (select regexp_replace(xml_column, '\n|\r', '', 'g') from resource ) to stdout" > output.txt