这里的操作是基于Python3平台。
在使用Python处理XML的问题上,首先遇到的是编码问题。
Python并不支持gb2312,所以面对encoding="gb2312"的XML文件会出现错误。Python读取的文件本身的编码也可能导致抛出异常,这种情况下打开文件的时候就需要指定编码。此外就是XML中节点所包含的中文。
我这里呢,处理就比较简单了,只需要修改XML的encoding头部。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#!/usr/bin/env python import os, sys import re def replaceXmlEncoding(filepath, oldEncoding = 'gb2312' , newEncoding = 'utf-8' ): f = open (filepath, mode = 'r' ) content = f.read() content = re.sub(oldEncoding, newEncoding, content) f.close() f = open (filepath, mode = 'w' ) f.write(content) f.close() if __name__ = = "__main__" : replaceXmlEncoding( './ActivateAccount.xml' ) |
接着是使用xml.etree.ElementTree来操作XML文件。
在一个类里面定义__call__函数可以使得该类可调用,比如下面代码的最后几行,在__main__函数中。这也很突出地体现了在Python的世界里,一切都是对象,包括对象本身 :)
一直觉得__main__函数用来测试真是蛮好用的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
#!/usr/bin/env python import os, re import xml.etree.ElementTree as etree Locale_Path = "./locale.txt" class xmlExtractor( object ): def __init__( self ): pass def __call__( self , filepath): retDict = {} f = open (filepath, 'r' ) Line = len ( open (filepath, 'r' ).readlines()) retDict[ 'Line' ] = Line tree = etree.parse(f) root = tree.find( "ResItem" ) Id = root.get( "ID" ) retDict[ 'Title' ] = Id resItemCnt = len ( list (root.findall( "ResItem" ))) + 1 retDict[ 'ResItemCount' ] = resItemCnt retDict[ 'ChineseTip' ] = 'None' for child in root: attrDict = child.attrib keyword = "Name" if (keyword in attrDict.keys() and attrDict[ 'Name' ] = = "Caption" ): if len (child.attrib[ 'Value' ]) > 1 : if child.attrib[ 'Value' ][ 0 ] = = '~' : title = child.attrib[ 'Value' ][ 1 :] else : title = child.attrib[ 'Value' ][ 0 :] #print(title) chs = open (Locale_Path).read() pattern = '<String id="' + title + '">[^>]+>' m = re.search(pattern, chs) if m ! = None : realTitle = re.sub( '<[^>]+>' , '', m.group( 0 )) retDict[ 'ChineseTip' ] = realTitle f.close() return retDict if __name__ = = "__main__" : fo = xmlExtractor() d = fo( './ActivateAccount.xml' ) print (d) |
最后,就是入口文件,导入上面两个文件,使用xml.dom和os.listdir来递归处理XML文件,并生成一个结果集。
一直觉得Python的UnboundLocalError错误挺有意思的,不知道是不是符号表的覆盖问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
#!/usr/bin/env python from xmlExtractor import * from replaceXmlEncoding import * from xml.dom import minidom,Node doc = minidom.Document() extractor = xmlExtractor() totalLines = 0 totalResItemCnt = 0 totalXmlFileCnt = 0 totalErrorCnt = 0 errorFileList = [] xmlRoot = doc.createElement( "XmlResourceFile" ) doc.appendChild(xmlRoot) def myWalkDir(level, path): global doc, extractor, totalLines, totalResItemCnt, totalXmlFileCnt global totalErrorCnt, errorFileList global xmlRoot for i in os.listdir(path): if i[ - 3 :] = = 'xml' : totalXmlFileCnt + = 1 try : #先把xml的encoding由gb2312转换为utf-8 replaceXmlEncoding(path + '\\' + i) #再提取xml文档中需要的信息 info = extractor(path + '\\' + i) #在上述两行代码没有出现异常的基础上再创建节点 #print(info) #print(type(i)) xmlNode = doc.createElement( "XmlFile" ) xmlRoot.appendChild(xmlNode) xmlName = doc.createElement( "Filename" ) xmlName.setAttribute( 'Value' , i) #xmlName.appendChild(doc.createTextNode(i)) xmlNode.appendChild(xmlName) filePath = doc.createElement( "Filepath" ) filePath.setAttribute( 'Value' , path[ 34 :]) #filePath.appendChild(doc.createTextNode(path[1:])) xmlNode.appendChild(filePath) titleNode = doc.createElement( "Title" ) titleNode.setAttribute( 'Value' , str (info[ 'Title' ])) #titleNode.appendChild(doc.createTextNode(str(info['Title']))) xmlNode.appendChild(titleNode) chsNode = doc.createElement( "ChineseTip" ) chsNode.setAttribute( 'Value' , str (info[ 'ChineseTip' ])) #chsNode.appendChild(doc.createTextNode(str(info['Chinese']))) xmlNode.appendChild(chsNode) resItemNode = doc.createElement( "ResItemCount" ) resItemNode.setAttribute( 'Value' , str (info[ 'ResItemCount' ])) #resItemNode.appendChild(doc.createTextNode(str(info['ResItemCount']))) xmlNode.appendChild(resItemNode) lineNode = doc.createElement( "LineCount" ) lineNode.setAttribute( 'Value' , str (info[ 'Line' ])) #lineNode.appendChild(doc.createTextNode(str(info['Line']))) xmlNode.appendChild(lineNode) descNode = doc.createElement( "Description" ) descNode.setAttribute( 'Value' , '') #descNode.appendChild(doc.createTextNode('')) xmlNode.appendChild(descNode) except Exception as errorDetail: totalErrorCnt + = 1 errorFileList.append(path + '\\' + i) print (path + '\\' + i, errorDetail) if os.path.isdir(path + '\\' + i): myWalkDir(level + 1 , path + '\\' + i) if __name__ = = "__main__" : path = os.getcwd() + '\\themes' myWalkDir( 0 , path) print (totalXmlFileCnt, totalErrorCnt) #print(doc.toprettyxml(indent = " ")) resultXml = open ( "./xmlResourceList.xml" , "w" ) resultXml.write(doc.toprettyxml(indent = " " )) resultXml.close() |
希望本文所述对大家Python程序设计有所帮助。