无法划分一个 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