龙空技术网

实战PyQt5: 127-处理XML文档

爱好史地的coder 224

前言:

目前咱们对“pythonandxml”大致比较关怀,小伙伴们都需要学习一些“pythonandxml”的相关知识。那么小编在网络上收集了一些关于“pythonandxml””的相关资讯,希望我们能喜欢,同学们快快来学习一下吧!

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):         returnif not doc.setContent(file):         file.close()         returnfile.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 sysfrom PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt5.QtCore import Qt, QFile, QIODevice, QModelIndex, QAbstractItemModelfrom 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文档。使用QDomDocument解析XML文档。使用QTreeView显示XML。

前一篇: 实战PyQt5: 126-使用QFile进行文件操作

请多多关注,评论,收藏,点赞,和转发。

标签: #pythonandxml