【发布时间】:2025-12-20 10:45:06
【问题描述】:
提前感谢您的所有帮助!
我正在处理一个大型文本数据集。每个文件包含多个.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)
在上面的示例文本上运行 sn-p 时,返回以下错误:
ParseError: not well-formed (invalid token): line 28, column 7
在广泛浏览了心爱的 * 之后,我已经尝试了以下替代方案:
- 使用
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)
此解决方案实际上适用于该文件,但对其他文件返回相同的错误。总体问题是数据集相当庞大和复杂。该脚本必须在服务器上运行,不可能为所有个别情况编写小的变通方法或测试每个文件。
其他帖子上的一些 cmets 建议“修复生成文件而不是 .xml 文件本身的过程”。但是,鉴于数据集是外部提供的,这根本不可行。
- 作为另一种可能性,我尝试在解析之前对文件进行解码和重新编码,因为这似乎已经解决了其他用户的问题(尽管有些人提到该解决方案似乎不适用于较新的版本)。这对我也不起作用。
- 作为最后一个选项,我尝试使用
BeautifulSoup。我对这个选项有两个问题:- 使用
lxml解析器给我留下了一个空的解析树 - 使用标准 bs4 解析器/或
html.parser会导致解析树,但是,结构似乎被搞砸了,以至于在我的代码的后续步骤中读取适当的子级失败。
- 使用
我正在运行以下版本(在寡妇机器上):
- 蟒蛇(蟒蛇):3.8.10
- lxml:4.6.3
- beautifulsoup4: 4.9.3
如果有任何提示或建议,我们将不胜感激。非常感谢!
【问题讨论】:
-
所以看起来你的问题是
\\x0b,它是一个垂直标签。目前尚不清楚这是否具有任何语义含义,但我认为您最终可能需要在解析之前清理此 XML。 -
@KyleParsons 非常感谢您的快速回复!很抱歉不得不删除很多文本(鉴于它是外部的,我不得不让它基本上毫无意义)。无论哪种方式,我实际上都在考虑使用正则表达式。但是,正如我在问题中提到的,数据集非常庞大,几乎不可能知道哪些标记可能会在其他数据示例中产生错误(如果不相同)。您是否想到了任何足够通用的清洁步骤 - 希望 - 处理这些问题,但又不是太笼统且可能具有破坏性?非常感谢任何 cmets!
-
@KyleParsons 快速更新:
clean = re.sub('\x0b','', EXAMPLE.decode())然后ET.fromstring(clean)似乎至少解决了这个特定案例的问题!但是,我几乎可以肯定,其他元素可能会在其他文件中引发类似的错误。有没有办法动态读出麻烦的令牌,然后用re将其删除,例如tryexcept声明还是什么?谢谢!
标签: python xml parsing beautifulsoup elementtree