Mo2*_*Mo2 2 python xml text file-comparison
我是Python的新手.我第二次编码.此脚本的要点是获取包含数千行文件名(sNotUsed文件)的文本文件,并将其与大约50个XML文件进行匹配.XML文件每个最多可包含数千行,并且格式化为大多数XML.我不确定到目前为止代码的问题是什么.代码没有完全完成,因为我没有添加将输出写回XML文件的部分,但是当前的最后一行应至少打印一次.但事实并非如此.
两种文件格式的示例如下:
文本文件:
fileNameWithoutExtension1
fileNameWithoutExtension2
fileNameWithoutExtension3
etc.
Run Code Online (Sandbox Code Playgroud)
XML文件:
<blocks>
<more stuff="name">
<Tag2>
<Tag3 name="Tag3">
<!--COMMENT-->
<fileType>../../dir/fileNameWithoutExtension1</fileType>
<fileType>../../dir/fileNameWithoutExtension4</fileType>
</blocks>
Run Code Online (Sandbox Code Playgroud)
我的代码很远:
import os
import re
sNotUsed=list()
sFile = open("C:\Users\xxx\Desktop\sNotUsed.txt", "r") # open snotused txt file
for lines in sFile:
sNotUsed.append(lines)
#sNotUsed = sFile.readlines() # read all lines and assign to list
sFile.close() # close file
xmlFiles=list() # list of xmlFiles in directory
usedS=list() # list of S files that do not match against sFile txt
search = "\w/([\w\-]+)"
# getting the list of xmlFiles
filelist=os.listdir('C:\Users\xxx\Desktop\dir')
for files in filelist:
if files.endswith('.xml'):
xmlFile = open(files, "r+") # open first file with read + write access
xmlComp = xmlFile.readlines() # read lines and assign to list
for lines in xmlComp: # iterate by line in list of lines
temp = re.findall(search, lines)
#print temp
if temp:
if temp[0] in sNotUsed:
print "yes" # debugging. I know there is at least one match for sure, but this is not being printed.
Run Code Online (Sandbox Code Playgroud)
帮助 明确的事情:对不起,我想我的问题不是很清楚.我希望脚本逐行遍历每个XML,并查看该行的FILENAME部分是否与sNotUsed.txt文件的确切行匹配.如果匹配,那么我想从XML中删除它.如果该行与sNotUsed.txt中的任何行都不匹配,那么我希望它是新修改的XML文件(将覆盖旧文件)的输出的一部分.如果还不清楚,请告诉我.
编辑,工作代码
import os
import re
import codecs
sFile = open("C:\Users\xxx\Desktop\sNotUsed.txt", "r") # open sNotUsed txt file
sNotUsed=sFile.readlines() # read all lines and assign to list
sFile.close() # close file
search = re.compile(r"\w/([\w\-]+)")
sNotUsed=[x.strip().replace(',','') for x in sNotUsed]
directory=r'C:\Users\xxx\Desktop\dir'
filelist=os.listdir(directory) # getting the list of xmlFiles
# for each file in the list
for files in filelist:
if files.endswith('.xml'): # make sure it is an XML file
xmlFile = codecs.open(os.path.join(directory, files), "r", encoding="UTF-8") # open first file with read
xmlComp = xmlFile.readlines() # read lines and assign to list
print xmlComp
xmlFile.close() # closing the file since the lines have already been read and assigned to a variable
xmlEdit = codecs.open(os.path.join(directory, files), "w", encoding="UTF-8") # opening the same file again and overwriting all existing lines
for lines in xmlComp: # iterate by line in list of lines
#headerInd = re.search(search, lines) # used to get the headers, comments, and ending blocks
temp = re.findall(search, lines) # finds all strings that match the regular expression compiled above and makes a list for each
if temp: # if the list is not empty
if temp[0] not in sNotUsed: # if the first (and only) value in each list is not in the sNotUsed list
xmlEdit.write(lines) # write it in the file
else: # if the list is empty
xmlEdit.write(lines) # write it (used to preserve the beginning and ending blocks of the XML, as well as comments)
Run Code Online (Sandbox Code Playgroud)
有很多事情要说,但我会尽量保持简洁.
您应该使用带有下划线的小写作为局部变量.看看PEP8:Python代码样式指南.
with
语句使用该with
语句打开文件,请参阅:文件对象:http://docs.python.org/2/library/stdtypes.html#bltin-file-objects
Windows文件名中的反斜杠可能会导致Python程序出现问题.您必须使用双反斜杠转义字符串或使用原始字符串.
例如:如果您的Windows文件名是"dir\notUsed.txt"
,您应该像这样转义它:"dir\\notUsed.txt"
或使用原始字符串r"dir\notUsed.txt"
.如果你不这样做,"\n"
将被解释为换行符!
注意:如果需要支持Unicode文件名,可以使用Unicode原始字符串:ur"dir\notUsed.txt"
.
另请参阅StockOverFlow中的问题19065115.
将文件名存储在set
:它是一个没有重复的优化集合
not_used_path = ur"dir\sNotUsed.txt"
with open(not_used_path) as not_used_file:
not_used_set = set([line.strip() for line in not_used_file])
Run Code Online (Sandbox Code Playgroud)
在多次使用时编译正则表达式更有效.同样,您应该使用原始字符串来避免反斜杠解释.
pattern = re.compile(r"\w/([\w\-]+)")
Run Code Online (Sandbox Code Playgroud)
警告: os.listdir()
函数返回文件名列表而不是完整路径列表.请参阅Python文档中的此函数.
在你的榜样,你读了桌面目录'C:\Users\xxx\Desktop\dir'
用os.listdir()
.然后你想打开这个目录中的每个XML文件open(files, "r+")
.但这是错误的,直到您当前的工作目录不是您的桌面目录.经典用法是使用这样的os.path.join()
函数:
desktop_dir = r'C:\Users\xxx\Desktop\dir'
for filename in os.listdir(desktop_dir):
desktop_path = os.path.join(desktop_dir, filename)
Run Code Online (Sandbox Code Playgroud)
如果要提取文件名的扩展名,可以使用该os.path.splitext()
功能.
desktop_dir = r'C:\Users\xxx\Desktop\dir'
for filename in os.listdir(desktop_dir):
if os.path.splitext(filename)[1].lower() != '.xml':
continue
desktop_path = os.path.join(desktop_dir, filename)
Run Code Online (Sandbox Code Playgroud)
您可以使用理解列表简化此操作:
desktop_dir = r'C:\Users\xxx\Desktop\dir'
xml_list = [os.path.join(desktop_dir, filename)
for filename in os.listdir(desktop_dir)
if os.path.splitext(filename)[1].lower() == '.xml']
Run Code Online (Sandbox Code Playgroud)
如何解析XML文件?这是一个很好的问题!有几种可能性: - 使用正则表达式,高效但危险; - 使用SAX解析器,效率高但令人困惑且难以维护; - 使用DOM解析器,效率更低但更清晰...考虑使用lxml包(@see:http://lxml.de/)
这很危险,因为你读取文件的方式,你不关心XML编码.这很糟糕!确实非常糟糕!XML文件通常以UTF-8编码.您应该首先解码UTF-8字节流.一种简单的方法是使用codecs.open()打开编码文件.
for xml_path in xml_list:
with codecs.open(xml_path, "r", encoding="UTF-8") as xml_file:
content = xml_file.read()
Run Code Online (Sandbox Code Playgroud)
使用此解决方案,完整的XML内容将content
作为Unicode字符串存储在变量中.然后,您可以使用Unicode正则表达式来解析内容.
最后,您可以使用集合交集来查找给定XML文件是否包含带有文本文件的公共名称.
for xml_path in xml_list:
with codecs.open(xml_path, "r", encoding="UTF-8") as xml_file:
content = xml_file.read()
actual_set = set(pattern.findall(content))
print(not_used_set & actual_set)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
844 次 |
最近记录: |