6

On a low level what is QDomNode and QDomDocument in the PyQGIS context?

I comprehend that both QDomNode and QDomDocument are derived from PyQt. Hence, with my limited knowledge of PyQt, I simply do not know how to operate with these classes.

For instance, if I want to save attribute table settings with the writeXml() method from the QgsAttributeTableConfig class. But then I am petrified because I do know the gist of the required QDomNode.

from qgis.utils import iface

layer = iface.activeLayer()
attr_table_config = layer.attributeTableConfig()

attr_table_config.writeXml(...)
# What should be done here ?

Searching on GIS SE does not really provide any clarifications.

help(QgsVectorLayer().attributeTableConfig().writeXml) does not help at all.

Help on built-in function writeXml:

writeXml(...) method of qgis._core.QgsAttributeTableConfig instance
    writeXml(self, node: QDomNode)
    Serialize to XML on layer save
2
  • 2
    It looks like it wants an XML node, which must be part of a document. See this test for an example using a similar function
    – JGH
    Nov 23, 2023 at 23:38
  • @JGH, thank you so much for such a useful URL!
    – Taras
    Nov 26, 2023 at 19:23

2 Answers 2

6

Here is what QDomNode and QDomDocument are in the Qt context:

The QDomDocumentclass represents the entire XML document. Conceptually, it is the root of the document tree, and provides the primary access to the document's data.

The QDomNode class is the base class for all the nodes in a DOM tree.

DOM provides an interface to access and change the content and structure of an XML file. It makes a hierarchical view of the document (a tree view). ......

All DOM nodes in the document tree are subclasses of QDomNode. The document itself is represented as a QDomDocument object.

In the PyQGIS context, QDomDocument refers to XML structure used in XML-like files such as .qgs, .qml, .sld etc.

writeXml converts(serializes) the configuration data contained in attr_table_config object to XML text. But it requires a QDomNode object to write the data to that object. A QDomDocument object is also a QDomNode object. Therefore, you can pass a QDomDocument object to the function.

doc = QDomDocument("myAttributeTableConfig") 
attr_table_config .writeXml(doc)

What about later? Now you can save the configuration as XML.

f = QFile("c:/test/test.xml")
result = f.open(QFile.WriteOnly)
if result:
    stream = QTextStream(f)
    doc.save(stream, 2) #2: amount of space to indent a node.
    f.close()

Here is an exmple for a simple attribute table as shown in the image below :

<!DOCTYPE myAttributeTableConfig>
<attributetableconfig actionWidgetStyle="dropDown" sortOrder="0" sortExpression="">
  <columns>
    <column type="field" hidden="0" name="id" width="142"/>
    <column type="field" hidden="0" name="isim" width="300"/>
    <column type="actions" hidden="1" width="-1"/>
  </columns>
</attributetableconfig>

enter image description here

Or you can add the configuration to an existing XML atructure.

layer = iface.activeLayer()

# make xml document
doc = QDomDocument("FooBar") 

# add an element to xml
foobar = doc.createElement("foobarconfig")
# foobar is QDomElement. QDomElement is also QDomNode.

config = layer.attributeTableConfig()

# write the configuration to foobar element(node)
config.writeXml(foobar) 

# add foobar element to doc
doc.appendChild(foobar)

f = QFile("c:/test/test.xml")
result = f.open(QFile.WriteOnly)
if result:
    stream = QTextStream(f)
    doc.save(stream, 2)
    f.close()

Result:

<!DOCTYPE FooBar>
 <foobarconfig> <!--HERE -->
  <attributetableconfig actionWidgetStyle="dropDown" sortOrder="0" sortExpression="">
    <columns>
      <column type="field" hidden="0" name="id" width="142"/>
      <column type="field" hidden="0" name="isim" width="300"/>
      <column type="actions" hidden="1" width="-1"/>
    </columns>
  </attributetableconfig>
</foobarconfig>
0
5

After certain trials and errors, I was able to perform exporting/importing configurations of the layer's attribute table, see Saving and applying layout of columns in QGIS Attribute Table.

Despite a great answer from @KadirŞahbaz, I would like to add some basic details regarding the DOM and XML in the scope of PyQGIS.


The DOM : Document Object Model - defines a standard for accessing and manipulating documents (changing document's structure, style, or content) with a logical tree, e.g. HTML, SVG, or XML. Each branch of the tree ends in a node, and each node contains objects.

The XML DOM - is a standard for getting, changing, adding, and deleting XML elements. It presents an XML document as a tree structure.

The XML : eXtensible Markup Language - is a markup language and file format, designed to store and transport data, to be self-descriptive and both human- and machine-readable, and is a W3C Recommendation.

All XML elements can be accessed through the XML DOM.

The XML DOM is:

  • a standard object model for XML
  • a standard programming interface for XML
  • platform- and language-independent
  • a W3C standard

According to the XML DOM, everything in an XML document is a node:

  • The entire document is a document node
  • Every XML element is an element node
  • The text in the XML elements are text nodes
  • Every attribute is an attribute node
  • Comments are comment nodes

Now let's switch to QGIS. Obviously, it comes with some embedded XML Python Packages e.g. xml, lxml, xmlrpc, and others (possible to see with help("modules xml")). However, QGIS uses the QtXml module to provide a C++ implementation of the DOM standard for XML.

The PyQt5.QtXml module contains two previously mentioned classes:

class explanation
QDomDocument Represents an XML document (a text file with a tree structure)
QDomNode The base class for all the nodes in a DOM tree (a DOM model constructed as a tree of Objects)

So, how to use the writeXml() method?

First of all, it requires a node i.e. QDomNode. Simply saying a spot, where to to insert the structured content of the QgsAttributeTableConfig.

Secondly if one decides to export that node into something like XML looking, one needs a certain approach. So, the QDomDocument class can be used. It has some methods. Another approach was shown by @KadirŞahbaz with the QTextStream class for reading and writing text.


References:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.