我正在编写一个 Python 3.2 脚本来查找 Unicode XML 格式的文本文件中在 XML 1.0 中无效的字符。该文件本身不是 XML 1.0,因此它可以轻松包含 1.1 及更高版本支持的字符,但使用它的应用程序只能处理 XML 1.0 中有效的字符,因此我需要找到它们。
XML 1.0 不支持 \u0001-\u0020 范围内的任何字符,\u0009、\u000A、\u000D 和 \u0020 除外。除此之外,\u0021-\uD7FF 和 \u010000-\u10FFFF 也是支持的范围,但仅此而已。在我的 Python 代码中,我以这种方式定义了该正则表达式模式:
re.compile("[^\u0009\u000A\u000D\u0020\u0021-\uD7FF\uE000-\uFFFD\u010000-\u10FFFF]")
但是,下面的代码在我的示例文件中没有找到已知的错误字符(\u0007,'bell' 字符。)不幸的是,我无法提供示例行(专有数据)。
我认为问题出在两个地方之一:要么是错误的正则表达式模式,要么是我如何打开文件并按行读取 - 即编码问题。当然,我可能是错的。
这是相关的代码片段。
processChunkFile()
接受三个参数:chunkfile
是文件的绝对路径(在这种情况下,原始文件的 500,000 行的“块”)可能包含也可能不包含坏字符。outputfile
是要写入输出的可选的、预先存在的文件的绝对路径。verbose
是一个布尔标志,用于启用更详细的命令行输出。其余代码只是获取命令行参数(使用argparse
)并将单个大文件分解为较小的文件。(原始文件通常大于 4GB,因此需要“分块”。)
def processChunkFile(chunkfile, outputfile, verbose):
"""
Processes a given chunk file, looking for XML 1.0 chars.
Outputs any line containing such a character.
"""
badlines = []
if verbose:
print("Processing file {0}".format(os.path.basename(chunkfile)))
# open given chunk file and read it as a list of lines
with open(chunkfile, 'r') as chunk:
chunklines = chunk.readlines()
# check to see if a line contains a bad character;
# if so, add it to the badlines list
for line in chunklines:
if badCharacterCheck(line, verbose) == True:
badlines.append(line)
# output to file if required
if outputfile is not None:
with open(outputfile.encode(), 'a') as outfile:
for badline in badlines:
outfile.write(str(badline) + '\n')
# return list of bad lines
return badlines
def badCharacterCheck(line, verbose):
"""
Use regular expressions to seek characters in a line
which aren't supported in XML 1.0.
"""
invalidCharacters = re.compile("[^\u0009\u000A\u000D\u0020\u0021-\uD7FF\uE000-\uFFFD\u010000-\u10FFFF]")
matches = re.search(invalidCharacters, line)
if matches:
if verbose:
print(line)
print("FOUND: " + matches.groups())
return True
return False