Python处理XML格式数据的方法详解

作者:jasonblog 时间:2021-04-10 22:25:07 

本文实例讲述了Python处理XML格式数据的方法。分享给大家供大家参考,具体如下:

这里的操作是基于Python3平台。

在使用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()

PS:这里再为大家提供几款关于xml操作的在线工具供大家参考使用:

在线XML/JSON互相转换工具:
http://tools.jb51.net/code/xmljson

在线格式化XML/在线压缩XML:
http://tools.jb51.net/code/xmlformat

XML在线压缩/格式化工具:
http://tools.jb51.net/code/xml_format_compress

XML代码在线格式化美化工具:
http://tools.jb51.net/code/xmlcodeformat

希望本文所述对大家Python程序设计有所帮助。

标签:Python,XML
0
投稿

猜你喜欢

  • C#如何实现对sql server数据库的增删改查

    2024-01-18 06:49:09
  • PDO::setAttribute讲解

    2023-06-05 18:04:23
  • SQL Server分析服务性能优化浅析

    2010-01-16 13:30:00
  • mysql 批量更新与批量更新多条记录的不同值实现方法

    2024-01-18 22:56:18
  • Python面向对象编程(一)

    2023-04-27 15:02:13
  • ORACLE LATERAL-SQL-INJECTION 个人见解

    2009-03-04 10:34:00
  • 从git仓库中删除.idea文件夹的小妙招

    2022-10-29 04:12:00
  • Debugging JavaScript:throw与console

    2008-08-29 17:03:00
  • 如何解决在Azure上部署Sqlserver网络访问不了

    2024-01-14 07:47:38
  • win10下python3.5.2和tensorflow安装环境搭建教程

    2022-11-05 15:56:21
  • vue2.0 循环遍历加载不同图片的方法

    2024-05-08 10:24:50
  • TinkerPop框架查询Gremlin图实现过程详解

    2024-01-29 11:26:45
  • 清除SQL被注入恶意病毒代码的语句

    2010-03-03 09:59:00
  • 面向站长和网站管理员的Web缓存加速指南[翻译]

    2008-04-22 21:04:00
  • CSS控制鼠标样式变换方法

    2007-11-17 07:58:00
  • vue.js实现含搜索的多种复选框(附源码)

    2024-05-13 09:11:00
  • python右对齐的实例方法

    2022-01-15 20:59:52
  • CSS中的标点符号用法

    2008-10-03 11:58:00
  • 对python字典过滤条件的实例详解

    2022-01-28 14:02:30
  • Numpy如何检查数组全为零的几种方法

    2023-05-16 12:00:25
  • asp之家 网络编程 m.aspxhome.com