Python 元素树解析错误
Python Element Tree ParseError
提前感谢您的帮助!
我正在处理一个大型文本数据集。每个文件包含多个 .xml
个文件。
其中一个文件可能如下所示(重现下面提到的错误的最小示例):
'\'<?xml version="1.0" encoding="ISO-8859-1" ?>\n<!DOCTYPE doc SYSTEM "abnml-1.0b.dtd">\n<doc msize="000002515" md5="748077a08df8db4a6472a52ed7f31b87" sysId="sbknwsarchp1" destination="AW" distId=" " transmission-date=" " >\n<abnml publisher="ABC" docdate="20000101" product="ABC" seq="101" xml:lang="en-us" >\n<head>\n<copyright year="2000" holder="ABC & Company, Inc." ></copyright>\n<docdata>\n<abc>\n<ABC-news news-source="ABC" origin="AA" service-id="CO" >\n<abc-press/>\n<abc-urban>0</abc-urban>\n<abc-mdata brand="AB" temp-perm="P" retention="N" hot="N" original-source="FW" accession-number="11111" page-citation="" display-date="22000101T164800.000Z" >\n<abc-coding>\n<abc-industry>\n<c>I/BAN</c>\n<c>I/SCR</c>\n</abc-industry>\n<abc-sub>\n<c>N/CMR</c>\n<c>N/DJI</c>\n<c>N/DJN</c>\n<c>N/EWR</c>\n<c>N/WER</c>\n<c>N/BON</c>\n<c>N/ABS</c>\n<c>N/ABWI</c>\n<c>N/TPC</c>\n<c>N/Y2\x0b</c>\n</abc-sub>\n<abc-mark>\n<c>M/NND</c>\n</abc-mark>\n<abc-prod>\n<c>P/AS03</c>\n</abc-prod>\n</abc-cod>\n</djn-mdata>\n</abc-news>\n</abc>\n</docdata>\n</head>\n<body>\n<headline prefix="=" brand-display="AB" >\nJames Bond Is OK</headline>\n<text>\n<pre>\n \n </pre>\n<p>\n NEW --The new year. </p>\n<p>\n "It was as usual (N`w Year's Eve) night, on Monday," said the. </p>\n<p>\n at|the agency. </p>\n<p>\n The firm. </p>\n<p>\n In addition Jan. 1, 2200, didn't recommended early last year "repurchase" fist few days of January. involve wireéÛ measure." </p>\n<p>\n And, to be fair, mendátion: they've 2000, there isn't a need eurãÛ>+ </p>\n<p>\n (END) </p>\n<p>\n January 01, 2200 11:48 ET (16:48 GMT)</p>\n</text>\n</body>\n</abnml>\n</doc>\''
我的第一个提取必要部分的解决方案是使用 Python 的标准库 xml.etree.ElementTree
。请在下面找到一个最低工作示例:
import xml.etree.ElementTree as ET
with open('EXAMPLE.nml', "rt") as file:
contents = file.read()
root = ET.fromstring(contents)
当运行在上面的示例文本中使用片段时,返回以下错误:
ParseError: not well-formed (invalid token): line 28, column 7
在广泛浏览心爱的 Whosebug 之后,我已经尝试了以下替代方案:
- 使用
lxml.etree
库,逐条读取文件(因为它允许“恢复”选项):
:
from lxml import etree
with open('EXAMPLE.nml', "rb") as file:
contents = file.read()
parser = etree.XMLParser(recover=True)
root = etree.fromstring(contents,parser=parser)
此解决方案实际上适用于此文件,但是,returns其他文件也会出现同样的错误。总体问题是数据集相当庞大和复杂。该脚本必须 运行 在服务器上,不可能为所有个别情况编写小的解决方法或测试每个文件。
其他帖子的一些评论建议“修复生成文件的过程而不是 .xml 文件本身”。但是,鉴于数据集是外部提供的,这根本行不通。
- 作为另一种可能性,我尝试在解析之前解码和 re-encoding 文件,因为这似乎已经解决了其他用户的问题(尽管有些人提到该解决方案似乎在较新版本中不起作用)。这对我也不起作用。
- 作为最后一个选项,我尝试使用
BeautifulSoup
。这个选项有两个问题:
- 使用
lxml
解析器给我留下了一个空的解析树
- 使用标准 bs4 parser/or
html.parser
导致解析树,但是,结构似乎被搞乱了,以至于在后面的步骤中读出适当的 children我的代码失败了。
我运行正在使用以下版本(在 widows 机器上):
- python(蟒蛇):3.8.10
- lxml: 4.6.3
- beautifulsoup4: 4.9.3
如有任何提示或建议,我们将不胜感激。非常感谢!
再次感谢您的宝贵意见!
经过一些测试,我发现了两个可能的解决方案。因为 - 据我所知 - 它们似乎没有记录在例如所以,我希望它们对其他 运行 解决类似问题的人有用。
- 如问题中所述,我也尝试使用
BeautifulSoup
或bs4
。最初的问题可以通过以下方式解决:
:
from bs4 import BeautifulSoup as bs
import lxml
with open('EXAMPLE.nml', "rb") as file:
contents = file.read()
soup = bs(contents, features="lxml")
要使其正常工作,必须先安装 lxml
,然后再安装 bs4
。这应该会自动为 bs4
安装 lxml
解析器。如原问题中所述,缺点是生成的解析树具有不同的结构,必须调整后面的部分代码。
- 解决方案 2:其中一条评论将我推向了这个方向。我没有使用
bs4
解决方法,而是实现了以下代码:
:
from lxml import etree
import re
try:
parser = etree.XMLParser(ns_clean=True, recover=True)
root = etree.fromstring(contents,parser=parser)
except:
fixed = re.sub(r"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]", "", contents.decode()).encode()
parser = etree.XMLParser(ns_clean=True, recover=True)
root = etree.fromstring(fixed,parser=parser)
此解决方案的优点是无需更改其余代码。它似乎积极地解决了这个问题,即使使用 ns_clean=True, recover=True
参数,lxml
解析器似乎在某些文件上失败。
提前感谢您的帮助!
我正在处理一个大型文本数据集。每个文件包含多个 .xml
个文件。
其中一个文件可能如下所示(重现下面提到的错误的最小示例):
'\'<?xml version="1.0" encoding="ISO-8859-1" ?>\n<!DOCTYPE doc SYSTEM "abnml-1.0b.dtd">\n<doc msize="000002515" md5="748077a08df8db4a6472a52ed7f31b87" sysId="sbknwsarchp1" destination="AW" distId=" " transmission-date=" " >\n<abnml publisher="ABC" docdate="20000101" product="ABC" seq="101" xml:lang="en-us" >\n<head>\n<copyright year="2000" holder="ABC & Company, Inc." ></copyright>\n<docdata>\n<abc>\n<ABC-news news-source="ABC" origin="AA" service-id="CO" >\n<abc-press/>\n<abc-urban>0</abc-urban>\n<abc-mdata brand="AB" temp-perm="P" retention="N" hot="N" original-source="FW" accession-number="11111" page-citation="" display-date="22000101T164800.000Z" >\n<abc-coding>\n<abc-industry>\n<c>I/BAN</c>\n<c>I/SCR</c>\n</abc-industry>\n<abc-sub>\n<c>N/CMR</c>\n<c>N/DJI</c>\n<c>N/DJN</c>\n<c>N/EWR</c>\n<c>N/WER</c>\n<c>N/BON</c>\n<c>N/ABS</c>\n<c>N/ABWI</c>\n<c>N/TPC</c>\n<c>N/Y2\x0b</c>\n</abc-sub>\n<abc-mark>\n<c>M/NND</c>\n</abc-mark>\n<abc-prod>\n<c>P/AS03</c>\n</abc-prod>\n</abc-cod>\n</djn-mdata>\n</abc-news>\n</abc>\n</docdata>\n</head>\n<body>\n<headline prefix="=" brand-display="AB" >\nJames Bond Is OK</headline>\n<text>\n<pre>\n \n </pre>\n<p>\n NEW --The new year. </p>\n<p>\n "It was as usual (N`w Year's Eve) night, on Monday," said the. </p>\n<p>\n at|the agency. </p>\n<p>\n The firm. </p>\n<p>\n In addition Jan. 1, 2200, didn't recommended early last year "repurchase" fist few days of January. involve wireéÛ measure." </p>\n<p>\n And, to be fair, mendátion: they've 2000, there isn't a need eurãÛ>+ </p>\n<p>\n (END) </p>\n<p>\n January 01, 2200 11:48 ET (16:48 GMT)</p>\n</text>\n</body>\n</abnml>\n</doc>\''
我的第一个提取必要部分的解决方案是使用 Python 的标准库 xml.etree.ElementTree
。请在下面找到一个最低工作示例:
import xml.etree.ElementTree as ET
with open('EXAMPLE.nml', "rt") as file:
contents = file.read()
root = ET.fromstring(contents)
当运行在上面的示例文本中使用片段时,返回以下错误:
ParseError: not well-formed (invalid token): line 28, column 7
在广泛浏览心爱的 Whosebug 之后,我已经尝试了以下替代方案:
- 使用
lxml.etree
库,逐条读取文件(因为它允许“恢复”选项):
:
from lxml import etree
with open('EXAMPLE.nml', "rb") as file:
contents = file.read()
parser = etree.XMLParser(recover=True)
root = etree.fromstring(contents,parser=parser)
此解决方案实际上适用于此文件,但是,returns其他文件也会出现同样的错误。总体问题是数据集相当庞大和复杂。该脚本必须 运行 在服务器上,不可能为所有个别情况编写小的解决方法或测试每个文件。
其他帖子的一些评论建议“修复生成文件的过程而不是 .xml 文件本身”。但是,鉴于数据集是外部提供的,这根本行不通。
- 作为另一种可能性,我尝试在解析之前解码和 re-encoding 文件,因为这似乎已经解决了其他用户的问题(尽管有些人提到该解决方案似乎在较新版本中不起作用)。这对我也不起作用。
- 作为最后一个选项,我尝试使用
BeautifulSoup
。这个选项有两个问题:- 使用
lxml
解析器给我留下了一个空的解析树 - 使用标准 bs4 parser/or
html.parser
导致解析树,但是,结构似乎被搞乱了,以至于在后面的步骤中读出适当的 children我的代码失败了。
- 使用
我运行正在使用以下版本(在 widows 机器上):
- python(蟒蛇):3.8.10
- lxml: 4.6.3
- beautifulsoup4: 4.9.3
如有任何提示或建议,我们将不胜感激。非常感谢!
再次感谢您的宝贵意见!
经过一些测试,我发现了两个可能的解决方案。因为 - 据我所知 - 它们似乎没有记录在例如所以,我希望它们对其他 运行 解决类似问题的人有用。
- 如问题中所述,我也尝试使用
BeautifulSoup
或bs4
。最初的问题可以通过以下方式解决:
:
from bs4 import BeautifulSoup as bs
import lxml
with open('EXAMPLE.nml', "rb") as file:
contents = file.read()
soup = bs(contents, features="lxml")
要使其正常工作,必须先安装 lxml
,然后再安装 bs4
。这应该会自动为 bs4
安装 lxml
解析器。如原问题中所述,缺点是生成的解析树具有不同的结构,必须调整后面的部分代码。
- 解决方案 2:其中一条评论将我推向了这个方向。我没有使用
bs4
解决方法,而是实现了以下代码:
:
from lxml import etree
import re
try:
parser = etree.XMLParser(ns_clean=True, recover=True)
root = etree.fromstring(contents,parser=parser)
except:
fixed = re.sub(r"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]", "", contents.decode()).encode()
parser = etree.XMLParser(ns_clean=True, recover=True)
root = etree.fromstring(fixed,parser=parser)
此解决方案的优点是无需更改其余代码。它似乎积极地解决了这个问题,即使使用 ns_clean=True, recover=True
参数,lxml
解析器似乎在某些文件上失败。