实战PyQt5: 127-处理XML文档
xsobi 2024-11-24 23:34 19 浏览
XML文档的简单和易扩展属性使其可以很方便地在任何程序中读/写数据。 比如在QT开发中,其常见的ui,qrc 后缀的文件都是一种XML格式的文档。QT提供类 QDomDocument来处理XML文档。
QDomDocment简介
QDomDOcument类代表整个XML文档。从概念上讲,它是文档树的根,并提供对文档的访问。由于元素(elment), 文本节点(text node), 注释(comment),处理指令(processing instruction)等都包含在XML文档内,因此QDomDocument类中也包含了创建这里对象的函数。QDomDocument创建的节点对象都具有ownerDocument()函数,该函数将它们与其上下文(context)中创建的文档相关联。
解析后的XML文档在内部由对象数来表示,可以使用各种QDom类访问这些对象。所有的QDom类仅引用内部树中的对象。一旦引用它们的最后一个QDom对象或者QDomDocument本身被删除时,DOM树中的内部对象将被删除。
注意:如果XML文档很大时,则Dom数可能会占用大量内存,在这种情况下,建议使用QXmlStreamreader或QXmlQuery类来处理这类XML文档。
使用QDom类通常按如下方式使用:
doc = QDomDocument('mydoc')
file = QFile('mydoc.xml')
if not file.open(QIOdevice.Readonly):
return
if not doc.setContent(file):
file.close()
return
file.close()
#打印最外层元素的直接联系的子元素的所有元素的名称
docElem = doc.documentElement()
node = docElem.firstChild()
while not node.isNull():
elem = node.toElement() #尝试将节点转换成元素
if no elem.isNull():
print(elem.tagName()
node = node.nextSibling()
#在文档的末尾添加一个新元素
elem = doc.createElement('img')
elem.setAttribute('src', 'myimage.png')
docElem.appendChild(elem)
下面的代码使用DOM创建XML文档:
doc = QDomDocument('myXML')
root = doc.createElement('myXML')
doc.appendChild(root)
tag = doc.createElement('Greeting')
root.appendChild(tag)
txt = doc.createTextNode('Hello World')
tag.appendChild(txt)
xml = doc.toString()
QDocument常用函数:
- toString(self): 将已解析的文档转回其文本表示方式。
- setContent(self, ...): 将指定的文本设置为XML文档内容,函数会尝试检测XML规范要求的文档编码。
- nodeType(self): 返回DocumentNode。
- documentElement(self): 返回文档的根元素。
- elementById(self, elementId): 返回其ID等于elementId的元素。如果未找到具有ID的元素,则此函数返回None。
- elementsByTagName(self, tagname): 返回一个QDomNodeList,其中包含名称为tagname的文档中的所有元素。节点列表的顺序是在元素树的预遍历中遇到它们的顺序。
- createElement(self, tagname): 创建一个名为tagname的新元素,可以将其插入DOM树。
- createTextNode(self, value): 为可插入文档树的字符串value创建文本节点。
- createComment(self, value): 为插入文档中的字符串value创建新注释。
- createAttribute(self, name): 创建一个名为name的新属性,可以将其插入元素属性中。
QDOM的一些常用类
除了QDomDocument以外,还有一些经常使用的DOM类:
- QDomNode: DOM树中所有节点的基类。
- QDomElement: 表示DOM树中的一个元素。
- QDomText: 表示已解析的XML文档中的文本数据。
- QXmlStreamReader: 提供了一个快速解析器,用于通过简单的流API读取格式正确的XML。
- QXmlQuery: 编译并执行以XQuery语言编写的查询。QXmlQuery通常用于查询XML数据,但它也可以查询已建模为XML的非XML数据。
测试
使用QTreeView按树的方式来显示QDomDocument解析的XML文件,完整代码如下:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QFile, QIODevice, QModelIndex, QAbstractItemModel
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QMenu, QAction,
QFileDialog, QTreeView)
from PyQt5.QtXml import QDomDocument
class DomItem(object):
def __init__(self, node, row, parent=None):
self.domNode = node
#记录条目在其父条目中的位置
self.rowNumber = row
self.parentItem = parent
self.childItems = {}
def node(self):
return self.domNode
def parent(self):
return self.parentItem
def child(self, i):
if i in self.childItems:
return self.childItems[i]
if i >= 0 and i < self.domNode.childNodes().count():
childNode = self.domNode.childNodes().item(i)
childItem = DomItem(childNode, i, self)
self.childItems[i] = childItem
return childItem
return None
def row(self):
return self.rowNumber
class DomModel(QAbstractItemModel):
def __init__(self, doucment, parent=None):
super(DomModel, self).__init__(parent)
self.domDocument = doucment
self.rootItem = DomItem(self.domDocument, 0)
#列数
def columnCount(self, parent):
return 3
#设置数据
def data(self, index, role):
if not index.isValid():
return None
if role != Qt.DisplayRole:
return None
item = index.internalPointer()
node = item.node()
attributes = []
attributeMap = node.attributes()
if index.column() == 0:
return node.nodeName()
elif index.column() == 1:
for i in range(0, attributeMap.count()):
attribute = attributeMap.item(i)
attributes.append(attribute.nodeName() + '="' + attribute.nodeValue() + '"')
return ' '.join(attributes)
elif index.column() == 2:
value = node.nodeValue()
if value is None:
return ''
return ' '.join(node.nodeValue().split('\n'))
return None
def flags(self, index):
if not index.isValid():
return Qt.NoItemFlags
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
#设置表头各部分的标题信息
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
if section == 0:
return '名字'
if section == 1:
return '属性'
if section == 2:
return '值'
return None
#索引
def index(self, row, column, parent):
if not self.hasIndex(row, column, parent):
return QModelIndex()
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QModelIndex()
#父项
def parent(self, child):
if not child.isValid():
return QModelIndex()
childItem = child.internalPointer()
parentItem = childItem.parent()
if not parentItem or parentItem == self.rootItem:
return QModelIndex()
return self.createIndex(parentItem.row(), 0, parentItem)
#行数
def rowCount(self, parent):
if parent.column() > 0:
return 0
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
return parentItem.node().childNodes().count()
class DemoDomDocument(QMainWindow):
def __init__(self, parent=None):
super(DemoDomDocument, self).__init__(parent)
# 设置窗口标题
self.setWindowTitle('实战Qt for Python: XML文档处理演示')
# 设置窗口大小
self.resize(480, 360)
self.initUi()
def initUi(self):
self.initMenuBar()
self.xmlPath = ''
self.model = DomModel(QDomDocument(), self)
self.view = QTreeView(self)
self.view.setModel(self.model)
self.setCentralWidget(self.view)
def initMenuBar(self):
menuBar = self.menuBar()
menuFile = menuBar.addMenu('文件(&F)')
menuFile.addAction('打开文件(&F)...', self.openFile, 'Ctrl+O')
menuFile.addAction('退出(&X)', QApplication.instance().quit, 'Ctrl+Q')
def openFile(self):
path,_ = QFileDialog.getOpenFileName(self, 'OpenFile', self.xmlPath,
'XML files (*.xml);;HTML files (*.html);;'
'SVG files (*.svg);;User Interface files (*.ui)')
if path:
f = QFile(path)
if f.open(QIODevice.ReadOnly):
document = QDomDocument()
if document.setContent(f):
newModel = DomModel(document, self)
self.view.setModel(newModel)
self.model = newModel
self.xmlPath = path
f.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DemoDomDocument()
window.show()
sys.exit(app.exec())
运行结果如下图:
本文知识点
- QDomDocument代表整个XML文档。
- 使用QDomDocument解析XML文档。
- 使用QTreeView显示XML。
前一篇: 实战PyQt5: 126-使用QFile进行文件操作
请多多关注,评论,收藏,点赞,和转发。
相关推荐
- C/C++编程笔记:C++中的函数重载(c++如何实现函数重载)
-
函数重载是C++中的一项功能,其中两个或多个函数可以具有相同的名称,但可以具有不同的参数。当函数名称因不同的作业而被重载时,称为函数重载。在函数重载中,“函数”的名称应相同,而参数则应不同。函数重载...
- C/C++编程笔记:C++中的运算符重载
-
在C++中,我们可以使运算符为用户定义的类工作。这意味着C++能够为运算符提供数据类型的特殊含义,这种能力称为运算符重载。例如,我们可以在String之类的类中重载运算符'+',以...
- 变频器如何区分重载和轻载?我们应该如何进行选择?
-
在选择变频器的过程中,重载和轻载是两个非常重要的参数。它是我们选择变频器的先决条件。1、那什么是轻型负载,轻型负载有哪些特征?轻载典型特征就是能拖动同等功率的负载,但是它的输出转距较小。像我们经常用到...
- 面试官:Java的重写和重载有什么区别?
-
先来看一段重写的代码吧。class LaoWang{ public void write() { &...
- Idea项目的创建和模块的导入Java中方法的三种调用方式和方法重载
-
一:如何创建工程和模块File-->New-->Project...EemptProject-->Next输入Finish-->Ok-->NewWindow关闭刚创建...
- C# - 构造方法重载与调用,析构方法(*) 068
-
构造方法重载普通方法构成重载的规则:方法名称一样,对应位置参数的类型或个数不同可以构成方法重载而构造方法的构成规则与此一样注意事项:如果方法的访问修饰符是private(还有其他的访问修饰符之后再说)...
- Java方法的重载与重写详解(java方法重载的规则是哪些)
-
1.方法的重载1.1.基本介绍在同一个类中,允许多个重名方法的存在,但要求形参列表不一致。比如:System.out.println(11)//输出整数System.out.println(...
- Go如何优雅的解决方法的重载(golang 优雅重启)
-
1、问题你是否曾经见过这样的代码funcHandler(){//...}funcHandler(timeOuttime.Duration){//..}fu...
- 你知道Java方法重载的本质吗?(java的方法重载是什么意思)
-
背景考大家一道题目,下面的类执行结果是什么???publicclassDispatcherClient{publicstaticvoidmain(String[]args)...
- Java方法重载&栈的了解(java方法重载有什么用)
-
函数的重载1.函数重载重载:在同一个类中,允许存在一个以上的同名函数,只要他们的参数个数或者参数类型不同即可。看一下示例:实例中函数名都为add,但是参数表(圆括号中的参数类型+形参)中的参数类型或者...
- 初学java常见问题:Java方法的重载是咋回事?
-
前言小千在之前给大家讲解构造方法的时候说过,在一个类中,可以定义多个构造方法,这叫做方法的重载!但是关于方法重载,具有有哪些要求和细节?很多小白还并不清楚,所以在今天的这篇文章中,小千给大家详细说说方...
- C#基础之方法重载(c# 重载运算符)
-
在具有相同名称但具有不同参数列表的类中定义多个方法时。此方法参数在参数的数量、类型和顺序上必须不同。这称为方法重载。方法重载是多态性的一种形式。C#中的方法重载方法重载的语法:以下是在C#中使用方...
- 观察者模式-Java实现(观察者模式实例)
-
介绍观察者模式的使用场景非常广泛,小到代码层面的解耦,达到架构层面的系统解耦,再或者到一些产品的设计思路,都有这种模式的影子。现在我们常说的基于事件驱动的架构,其实也是观察者模式的一种最佳实践。当我们...
- 如何使用Go实现观察者模式(观察者模式的使用场景)
-
#从今天起记录我的2023##头条创作挑战赛#观察者模式是一种设计模式,它允许对象之间的松散耦合,因为这些对象不需要知道彼此的细节信息,只需要知道如何通知其他对象,以便它们可以做出相应的响应。在g...
- JAVA实现观察者模式,其实真的很简单
-
#头条创作挑战赛#概述观察者模式,又叫发布/订阅模式(Publish-Subscribe)。定义对象之间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于他的对象都会收到通知并且执行对应的...
- 一周热门
- 最近发表
- 标签列表
-
- grid 设置 (58)
- 移位运算 (48)
- not specified (45)
- 导航栏 (58)
- context xml (46)
- scroll (43)
- dedecms模版 (53)
- c 视频教程下载 (33)
- listview排序 (33)
- characterencodingfilter (33)
- getmonth (34)
- label换行 (33)
- android studio 3 0 (34)
- html转js (35)
- 索引的作用 (33)
- checkedlistbox (34)
- xmlhttp (35)
- mysql更改密码 (34)
- 权限777 (33)
- htmlposition (33)
- 学校网站模板 (34)
- textarea换行 (34)
- 轮播 (34)
- asp net三层架构 (38)
- bash (34)