excel转xml
来源:互联网 发布:java配置文件的作用 编辑:程序博客网 时间:2024/05/17 23:18
python把excel文件转成xml文件。
策划用excel配置各种数据,程序在使用前,用python把该excel文件转换成xml文件,再在程序里面加载读取xml文件。
首先定好规则,我们是这样的,一个excel文件只允许第一个表格存放有效配置数字,列名字以c_开头表示此列只有客户端需要,以s_开头表示此列只有客户端需要,以_开头表示为无效配置数据(策划解释说明用),这样定好规则后,就能更清晰的知道哪些需要写入xml文件中,还有,规定每一个表格的第二行为对每一列名字的说明。 也就是说 第二行的数据是不要写入xml文件的。比如如下表格:
其中单元格为空的表示该行数据没有该列的属性,如表格中钻石道具没有颜色这一属性。
我们用python来实现转换,其实用java c c++ 都可以,但是做些小工具嘛,最好是用轻便而简单的语言实现,因为对效率不是那么的高,转换的时候,多花费个几秒钟也是可以接受的。所以就用python来写咯,对了最近node.js很火,也可以用js来写,原理都是一样的。
因为要读取excel文件,那么首先就要导入xlrd模块, 以下是我写的py代码:
# -*- coding: utf-8 -*-import osimport sysimport typesimport xlrdimport inspectimport shutilfrom time import localtime, strftimeEXL_PATH = ''XML_PATH = ''TEMP_EXL_PATH = './xls'TEMP_XML_PATH = './xml'LOG_PATH = './log'reload(sys) sys.setdefaultencoding('utf8')def getExlList(): exl_list = [] for (dirpath, dirnames, filenames) in os.walk(EXL_PATH): for filename in filenames: if os.path.splitext(filename)[1] == '.xls': exl_list.append(filename) return exl_listdef isChinese(stringCode): for ch in stringCode.decode('utf-8'): if u'\u4e00' <= ch <= u'\u9fff': return True return Falsedef makeDir(dirPath): if not os.path.exists(dirPath): os.mkdir(dirPath)def copyDir(sourceDir, destDir): if os.path.exists(destDir): shutil.rmtree(destDir) shutil.copytree(sourceDir,destDir)def copyAllFile(sourceDir, destDir): for(dirpath, dirnames, filenames) in os.walk(sourceDir): for filename in filenames: desFileName = destDir + '/' + filename shutil.copy(sourceDir + '/' + filename,desFileName)class enumColType: clientOnly = 0 #客户端专用 serverOnly = 1 #服务器专用 cleAndSer = 2 #cs都用 comment = 3 #cs都无需用def getColType(sourceString): if sourceString[0] == '_': return enumColType.comment elif sourceString[0:2] == 'c_': return enumColType.clientOnly elif sourceString[0:2] == 's_': return enumColType.serverOnly else: return enumColType.cleAndSerdef writeToXml(exlName): prefixFileName = exlName.split('.')[0] xmlFileName = prefixFileName + '.xml' xmlServerFileFullName = TEMP_XML_PATH + '/server/' + xmlFileName xmlClientFileFullName = TEMP_XML_PATH + '/client/' + xmlFileName fileClient = open(xmlClientFileFullName,'wb') fileClient.write('<?xml version="1.0" encoding="utf-8" ?>\n') fileClient.write('<root>\n') fileServer = open(xmlServerFileFullName,'wb') fileServer.write('<?xml version="1.0" encoding="utf-8" ?>\n') fileServer.write('<root>\n') exlFileFullName = TEMP_EXL_PATH + '/' + exlName exlData = xlrd.open_workbook(exlFileFullName,formatting_info = True,encoding_override="utf-8") table = exlData.sheets()[0] nrows = table.nrows ncols = table.ncols print 'nrows:' + str(nrows) + ' ncols:' + str(ncols) fileLog.write('xlsName:%s, nrows:%s, ncols:%s\n' %(exlName,str(nrows),str(ncols))) firstRows = table.row_values(0) for rownum in range(2,nrows): stringClient = '<element' stringServer = '<element' row = table.row_values(rownum) for colnum in range(ncols): if row[colnum] != '' and firstRows[colnum] != '': #单元格不为空 且列名不为空 if type(row[colnum]) is types.FloatType: row[colnum] = int(row[colnum]) colType = getColType(firstRows[colnum]) if colType == enumColType.cleAndSer: #cs 都用 tempString = ' %s="%s"' %( str(firstRows[colnum]), str(row[colnum]) ) stringClient += tempString stringServer += tempString elif colType == enumColType.clientOnly: #只客户端用 ss = str(firstRows[colnum])[2:] tempString = ' %s="%s"' %( ss, str(row[colnum]) ) stringClient += tempString elif colType == enumColType.serverOnly: #服务器专用 ss = str(firstRows[colnum])[2:] tempString = ' %s="%s"' %( ss, str(row[colnum]) ) stringServer += tempString stringClient += '/>\n' fileClient.write(stringClient) stringServer += '/>\n' fileServer.write(stringServer) fileClient.write('</root>') fileClient.close() fileServer.write('</root>') fileServer.close() fileLog.write('xlsName:%s transform success\n' %(exlName))if __name__ == "__main__": EXL_PATH = sys.argv[1] XML_PATH = sys.argv[2] print 'EXL_PATH = ' + EXL_PATH print 'XML_PATH = ' + XML_PATH makeDir(LOG_PATH) copyDir(EXL_PATH,TEMP_EXL_PATH) makeDir(TEMP_XML_PATH) makeDir(TEMP_XML_PATH + '/client') makeDir(TEMP_XML_PATH + '/server') fileLog = open(LOG_PATH + '/' + strftime("%Y%m%d%H%M%S", localtime()) + '.txt', "wb") fileLog.write('from %s to %s\n' %(EXL_PATH,XML_PATH)) allExlFiles = getExlList() for(exlFile) in allExlFiles: print 'exchange file : ' + exlFile writeToXml(exlFile) copyAllFile(TEMP_XML_PATH + '/client',XML_PATH) fileLog.close()
具体就是 读取excel的第一个表格,然后遍历每一行,分情况,把要写入文件字段累加,最后写入xml文件,代码很简单,但是里面包括了一些和工程涉及的东西,不过很容易看懂,也不影响。
那么上面的表格经过转换之后,就会得到两个文件,一个是给服务器的,一个是给客户端的。其中服务器xml如下:
<?xml version="1.0" encoding="utf-8" ?><root><element itemId="0001" itemNameId="10001" itemPrice="10"/><element itemId="0002" itemNameId="10002" itemPrice="50"/><element itemId="0003" itemNameId="10003" itemPrice="50"/></root>
客服端xml文件如下:
<?xml version="1.0" encoding="utf-8" ?><root><element itemId="0001" itemNameId="10001"/><element itemId="0002" itemNameId="10002" itemColor="red"/><element itemId="0003" itemNameId="10003" itemColor="red"/></root>
注意这两个文件内容的区别 和excel之前的区别。
这样就实现了策划按照规定来填写表格,我们程序负责转化就是了。
改进和优化:有个时候,表格行数很多,就会有一个问题,什么问题,相同的字符串太多,因为每一行的属性名字就是每一列的名字,比如上面的表格,如果有1000行,那么这个xml中就会有1000 个 字符串 “itemId”,并且其余的属性也基本那么多,这样一来就会想到,压缩了,其实zip文件压缩的最基本的原理就是重复多次出现的字符串,用一个标识代替。 我们可以首先给每一列的名字,用较短的字符串来表示,比如第一列用c0代替,如上xml可以这么写:
<?xml version="1.0" encoding="utf-8" ?><root><column c0="itemId" c1="itemNameId" c2="itemPrice" c3="itemColor"/><element c0="0001" c1="10001"/><element c0="0002" c1="10002" c3="red"/><element c0="0003" c1="10003" c3="red"/></root>
如果表格中行数较少,影响不大,但是表格行数多了,效果就显示出来了,无论是xml文件的大小,还有在内存中解析所占的内存,都是一份不小的优化了。 至于具体怎么实现,这里就不贴代码了,首先写入xml的原理无非新建一个列的索引,把第一列名写到column。 再以后写内容的时候,不写列名,而写列的索引。 至于解析也一样,读到某一行数据 再把属性索引对应到colum 得到真正的属性名字,就ok了。
- Python excel转xml
- testlink xml转excel
- excel转xml
- Excel转XML
- C# 将Excel转xml
- xml excel
- XML转Excel或Excel转XML|tinyxml简单使用|C++使用excel
- testlink中excel转XML格式
- 使用office2010将Excel转xml
- java+dom4j解析xml转excel
- Excel转XML,和生成bean对象
- java--Excel读取及转XML
- xml,excel导入数据库
- xml模板导出Excel
- c# XML to Excel
- ruby xml excel
- Excel To Xml
- DataGridView导出excel/xml
- Git – fatal: Unable to create '路径/.git/index.lock’: File exists.的解决办法
- Android application
- Oracle序列(Sequence)创建、使用、修改、删除
- github上Fuchsia项目相关文章翻译 - Getting Started(fuchsia-mirror/magenta/getting_started.md)
- JSP----jQuery插件ContextMenu生成右键菜单
- excel转xml
- 面试经历
- 周记2016.8.1
- 正则表达式
- JTAG工作原理
- uC/OSIII时钟节拍处理过程
- Android群英传---View、ViewGroup的测量和绘制
- 运行hadoop fs -ls 命令显示本地目录问题
- 百练+DFS+就是一个典型的DFS框架