您的位置:首页 > 编程语言 > Python开发

使用Python处理XML

2011-07-28 20:20 465 查看
很久没有写博文了,也很久没有碰Python了。刚好工作需要,小小动手了下。
因为是在新机器上,所以就直接装了Python 3,反正以后也是要适应,不如早点。

在使用Python处理XML的问题上,首先遇到的是编码问题。
Python并不支持gb2312,所以面对encoding="gb2312"的XML文件会出现错误。Python读取的文件本身的编码也可能导致抛出异常,这种情况下打开文件的时候就需要指定编码。此外就是XML中节点所包含的中文。
我这里呢,处理就比较简单了,只需要修改XML的encoding头部。

#!/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__函数用来测试真是蛮好用的。

#!/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错误挺有意思的,不知道是不是符号表的覆盖问题。

#!/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()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: