无法划分一个 QDomDocument() 节点的 xml 个元素,并使用 pyqt5 将这些元素附加到 DOM 模型
Cannot divide xml elements of one QDomDocument() node and append the elements to the DOM model with pyqt5
我有这段代码目前有效,可以直接查看 xml 文件:
from PyQt5.QtCore import QAbstractItemModel, QFile, QIODevice, QModelIndex, Qt
from PyQt5.QtWidgets import QApplication, QFileDialog, QMainWindow, QTreeView
from PyQt5.QtXml import QDomDocument, QDomElement
class DomItem(object):
def __init__(self, node, row, parent=None):
self.domNode = node
# Record the item's location within its parent.
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 0 <= 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, document, parent=None):
super(DomModel, self).__init__(parent)
self.domDocument = document
self.rootItem = DomItem(self.domDocument, 0)
def columnCount(self, parent):
# return 3
return 2
def data(self, index, role):
if not index.isValid():
return None
if role != Qt.DisplayRole:
return None
item = index.internalPointer()
node = item.node()
if index.column() == 0:
# print(node.nodeName())
if node.nodeName() != '#text':
return node.nodeName()
else:
return None
if index.column() == 1:
value = node.nodeValue()
if value is None:
return ''
else:
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 "Category"
if section == 1:
return "Name"
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 MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.fileMenu = self.menuBar().addMenu("&File")
self.fileMenu.addAction("&Open...", self.openFile, "Ctrl+O")
self.fileMenu.addAction("E&xit", self.close, "Ctrl+Q")
self.xmlPath = ""
self.model = DomModel(QDomDocument(), self)
self.view = QTreeView(self)
self.view.setModel(self.model)
self.setCentralWidget(self.view)
self.setWindowTitle("Simple DOM Model")
def openFile(self, filePath):
if filePath:
f = QFile(filePath)
if f.open(QIODevice.ReadOnly):
document = QDomDocument()
if document.setContent(f):
newModel = DomModel(document, self)
self.view.setModel(newModel)
self.view.expandAll()
self.model = newModel
self.xmlPath = filePath
f.close()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.resize(640, 480)
window.show()
window.openFile('your file full path')
sys.exit(app.exec_())
xml 文件是:
<repoCoordinates>
<name>repostructuretrials</name>
<branches>master</branches>
<submodules>
<submodule_0>
<name>gameengine</name>
<branches>*master,remotes/origin/develop,remotes/origin/feature/NormalMappingAndTextureCombination,remotes/origin/feature/light,remotes/origin/feature/particleEmitter,remotes/origin/master</branches>
</submodule_0>
<submodule_1>
<name>GraphicEngineOpenGLBasics</name>
<branches>feature/shadows,*master,remotes/origin/develop,remotes/origin/feature/billboards,remotes/origin/feature/shadows,remotes/origin/master</branches>
</submodule_1>
</submodules>
</repoCoordinates>
我得到了这个:
代码量大但不是很复杂。
我的问题是我想将每个分支名称作为树模型中的不同项,并且所有用逗号分隔的值都是模型的唯一项。我尝试解析 xml,并使用 QDomElement()
class 尝试将子节点附加到我的节点,以便能够分别选择每个分支。
我想用“,”拆分所有分支名称,并将这些节点添加到我的 DOM。
如果 QDomDocument
class 不是最好的方法,我将不胜感激任何对此的帮助,以及处理此问题的任何建议。
非常感谢
这是一个非常基本的尝试,可以实现您想要的。
它所做的是在节点检测到其名称为 "branches" 时创建子子节点,以便项目模型可以将它们视为实际的子节点。通过在父 childItems
dict 上写入自己的索引来手动创建子项,以便模型可以在父项之间导航。
请记住,这种方法远非完美:例如,模型和相关 DOM 不是写安全的(我对 QtXml 模块没有那么多的经验)。
class DomItem(object):
# ...
def child(self, i):
if i in self.childItems:
return self.childItems[i]
if 0 <= i < self.domNode.childNodes().count():
childNode = self.domNode.childNodes().item(i)
childItem = DomItem(childNode, i, self)
self.childItems[i] = childItem
if childNode.nodeName() == 'branches':
# based on your example xml there should be only one child entry
# for each "branches" node, but, just in case, let's cycle amongst
# every possible child node
subChildNodes = childNode.childNodes()
childIndex = 0
for c in range(subChildNodes.count()):
subChild = subChildNodes.at(c)
for tag in subChild.nodeValue().split(','):
branch = childNode.ownerDocument().createElement(tag)
childNode.appendChild(branch)
branchItem = DomItem(branch, childIndex, childItem)
childItem.childItems[childIndex] = branchItem
childIndex += 1
return childItem
return None
我有这段代码目前有效,可以直接查看 xml 文件:
from PyQt5.QtCore import QAbstractItemModel, QFile, QIODevice, QModelIndex, Qt
from PyQt5.QtWidgets import QApplication, QFileDialog, QMainWindow, QTreeView
from PyQt5.QtXml import QDomDocument, QDomElement
class DomItem(object):
def __init__(self, node, row, parent=None):
self.domNode = node
# Record the item's location within its parent.
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 0 <= 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, document, parent=None):
super(DomModel, self).__init__(parent)
self.domDocument = document
self.rootItem = DomItem(self.domDocument, 0)
def columnCount(self, parent):
# return 3
return 2
def data(self, index, role):
if not index.isValid():
return None
if role != Qt.DisplayRole:
return None
item = index.internalPointer()
node = item.node()
if index.column() == 0:
# print(node.nodeName())
if node.nodeName() != '#text':
return node.nodeName()
else:
return None
if index.column() == 1:
value = node.nodeValue()
if value is None:
return ''
else:
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 "Category"
if section == 1:
return "Name"
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 MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.fileMenu = self.menuBar().addMenu("&File")
self.fileMenu.addAction("&Open...", self.openFile, "Ctrl+O")
self.fileMenu.addAction("E&xit", self.close, "Ctrl+Q")
self.xmlPath = ""
self.model = DomModel(QDomDocument(), self)
self.view = QTreeView(self)
self.view.setModel(self.model)
self.setCentralWidget(self.view)
self.setWindowTitle("Simple DOM Model")
def openFile(self, filePath):
if filePath:
f = QFile(filePath)
if f.open(QIODevice.ReadOnly):
document = QDomDocument()
if document.setContent(f):
newModel = DomModel(document, self)
self.view.setModel(newModel)
self.view.expandAll()
self.model = newModel
self.xmlPath = filePath
f.close()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MainWindow()
window.resize(640, 480)
window.show()
window.openFile('your file full path')
sys.exit(app.exec_())
xml 文件是:
<repoCoordinates>
<name>repostructuretrials</name>
<branches>master</branches>
<submodules>
<submodule_0>
<name>gameengine</name>
<branches>*master,remotes/origin/develop,remotes/origin/feature/NormalMappingAndTextureCombination,remotes/origin/feature/light,remotes/origin/feature/particleEmitter,remotes/origin/master</branches>
</submodule_0>
<submodule_1>
<name>GraphicEngineOpenGLBasics</name>
<branches>feature/shadows,*master,remotes/origin/develop,remotes/origin/feature/billboards,remotes/origin/feature/shadows,remotes/origin/master</branches>
</submodule_1>
</submodules>
</repoCoordinates>
我得到了这个:
代码量大但不是很复杂。
我的问题是我想将每个分支名称作为树模型中的不同项,并且所有用逗号分隔的值都是模型的唯一项。我尝试解析 xml,并使用 QDomElement()
class 尝试将子节点附加到我的节点,以便能够分别选择每个分支。
我想用“,”拆分所有分支名称,并将这些节点添加到我的 DOM。
如果 QDomDocument
class 不是最好的方法,我将不胜感激任何对此的帮助,以及处理此问题的任何建议。
非常感谢
这是一个非常基本的尝试,可以实现您想要的。
它所做的是在节点检测到其名称为 "branches" 时创建子子节点,以便项目模型可以将它们视为实际的子节点。通过在父 childItems
dict 上写入自己的索引来手动创建子项,以便模型可以在父项之间导航。
请记住,这种方法远非完美:例如,模型和相关 DOM 不是写安全的(我对 QtXml 模块没有那么多的经验)。
class DomItem(object):
# ...
def child(self, i):
if i in self.childItems:
return self.childItems[i]
if 0 <= i < self.domNode.childNodes().count():
childNode = self.domNode.childNodes().item(i)
childItem = DomItem(childNode, i, self)
self.childItems[i] = childItem
if childNode.nodeName() == 'branches':
# based on your example xml there should be only one child entry
# for each "branches" node, but, just in case, let's cycle amongst
# every possible child node
subChildNodes = childNode.childNodes()
childIndex = 0
for c in range(subChildNodes.count()):
subChild = subChildNodes.at(c)
for tag in subChild.nodeValue().split(','):
branch = childNode.ownerDocument().createElement(tag)
childNode.appendChild(branch)
branchItem = DomItem(branch, childIndex, childItem)
childItem.childItems[childIndex] = branchItem
childIndex += 1
return childItem
return None