processing XML files with the Qdomdocument class in Qt
XML, all known as the Extended Markup Language (Extensible Markup Language). is a very convenient data exchange tool. Now the blog's subscription system output format is to meet the XML specification of the RSS format, as well as SVG vector graphics are also used in XML format.
After we have obtained a file in XML format, we need to parse it to extract the information provided by the Publisher. QT provides good support for XML, including the implementation of the DOM and the implementation of Sax.
The DOM is the abbreviation for the Document Object model, which is implemented as an object to be loaded into memory for processing, and then the developer can access each node in the object, each node corresponding to a tag in the XML file. The advantage of this approach is that the operation is very simple, the disadvantage is that the entire file needs to be put into memory, not suitable for processing too large files. The implementation of this method in Qt is qdomdocument, and this article is going to explain. Blog as the representative of the RSS file is not very large, suitable for processing in this way.
Sax is short for the simple API for XML, which is implemented by sequentially reading the document into memory and invoking the developer's pre-designed callback function when it encounters a tag or other stage. The disadvantage of this approach is the need for developers to write callback functions to handle different tags, the code is more complex, the advantage is that it can handle a large XML file. The implementation of this approach in Qt is called Qxmlstreamreader.
Below the —————— split line, the code explains ———-
1) If you need to use qdomdocument, please add a "QT + = xml" to your project. Pro file, otherwise it will not compile.
2)
Qdomdocument Doc; QFile file ("Rss.xml"); QString Errorstr;int ErrorLine; int errorcol;//setcontent is to assign the specified content to the qdomdocument resolution,//The first parameter can be Qbytearray or the file name, etc. if (!doc.setcontent (&file,true, &errorstr,&errorline,&errorcol)) {//If an error occurs, it will be entered here. Errorstr got an error stating that//errorline and Errorcol are the wrong rows and columns}
If the above steps are not wrong, then congratulations, you have got a complete Qdomdocument object doc, you can only access the child nodes or child nodes of the doc to get the contents of all the tags in the XML.
3)
You can get all the child node list qdomnodelist of Doc through Doc.childnodes (). Like what
Qdomnodelist list=doc.childnodes (); for (int i=0;i<list.count (); i++) {Qdomnode node=list.at (i);//A good style of course is to write the definition out: (//qdebug () << "node name is" < <node.nodename (); Qdebug () << "node type is" <<.nodetype ();}
By the above method you can know the name and type of each node, and the node name is the name of the tag. Print it out against the XML file and it's easy to see. The Qdomnode class is a parent class, and Qdomdocument is a subclass of Qdomnode, since most qdomnode types are qdomdocument. Then you can use the Todocument () The Qdomnode function converts the type of the qdomdocument into a.
QString text=node.toelement (). text ();
The above statement can take the text out of a node, which is the text part within the tag. The encoding obtained using this function is already in Unicode format and does not need to be converted.
using Qdomdocument in QT to read XML files
The Qdomdocument method makes it easy to parse an XML file, and each sub-object of qdomdocument corresponds to each sub-node of the XML, preserving the same hierarchy and allowing random access to the nodes in the XML. However, its disadvantage is that the entire XML file needs to be loaded into memory and not suitable for processing large files.
Today is to introduce the qxmlstreamreader, that is, in order to read the XML, each read a node, the application of the current node to do the corresponding processing (ignore or save). So this way is sax. No.
SAX is handled in a node-by-sequence manner, but it is not treated as a read node. When Sax encounters a node, it invokes a callback function that the user has written, which is a virtual function of the base class implementation, cannot change its name, and can only be handled differently depending on the parameters passed in, and the code will be more complex. However, the implementation of StreamReader is by the developer through the Readnext () read into a node, and then determine the node content, by the developer decide what function to deal with, corresponding to different node hierarchy implementation of different functions, maintainability is better.
The specific process is:
1. Create a Qxmlstreamreader class object
2. Set the XML file to be processed by Setdevice ()
3. Read the node in Readnext (),
4.a by Isstartelement () and Isendelement () is the start and end of the node
4.B can get the current node name by name ()
4.C can access the contents of the current node via Readelementtext ()
Now, let's take a look at my example of handling Rss2 code, which I read the title of each file in Rss2.
Because we need to implement our own processing function, we inherit from Qxmlstreamreader with a class Rssrader
Class Rssreader:public qxmlstreamreader{... }
You can use this class as follows.
RssReader reader;
Reader.read (&file); parameter is the Qiodevice pointer, file is the Qfile type,
Read is the function name that I implemented in the subclass, can be another name, see the implementation of Read ()
BOOL Rssreader::read (Qiodevice *device)
{
Setdevice (device);//This is a function of the base class for passing XML to the parser
while (!atend ()) {
Readnext (); This is the key function that reads the nodes
if (Isstartelement ()) {
if (name () = = "RSS") {
My implementation, the RSS processing, the other nodes ignore
Read_rss () manages the remaining nodes and returns when the RSS node ends
Read_rss ();
}
}
}
return!error ();
}
The implementation of READ_RSS is mainly concerned with nodes named Channel, other nodes ignoring
The node of XML is symmetrical, there must be an end in the beginning, and the mark of Judgment is
Isstartelement () and Isendelement ()
void Rssreader::read_rss () {
Qdebug () << "read RSS info";
while (!atend ()) {
Readnext ();
if (Isstartelement ()) {
if (name () = = "Channel") {
Read_channel ();
}
}
if (Isendelement ()) {
if (name () = = "RSS") {
Qdebug () << "end read RSS info";
Break
}
}
}
}
The function that reads the contents of the node is Readelementtext (), implemented by the base class
void Rssreader::read_item () {
while (!atend ()) {
Readnext ();
if (Isstartelement ()) {
if (name () = = "title") {
Qdebug () << "Title:" <<readelementtext ();
}
}
if (Isendelement ()) {
if (name () = = "Item") {
Break
}
}
http://www.cuteqt.com/blog/?p=247
http://www.cuteqt.com/blog/?p=358
In the "QQ Sticky Notes" project Group I am responsible for the implementation of the background XML operations, and now the XML used in the project related to the operation of a simple summary.
We know that there are two ways to manipulate XML, that is, Dom mode and sax mode. The main difference is that the DOM implementation is very simple, but not suitable for handling large files, and the SAX implementation is able to handle a large XML file, but requires the developer to write some complex code. QT provides an implementation class that corresponds to both the read, manipulate, and write XML, respectively, the Qdomdocument class and the Qxmlstreamreader class, because the files involved in the project are small, so we use the Qdomdocument class for processing.
The items involved in adding and deleting notes, corresponding to the corresponding tags in the XML file read, write and modify, the following are described below:
1. Create the node, write it to the XML file, and the main operations include:
1). Create root node: qdomelement root = Doc.documentelement ("Rootname");
2). Create element node: qdomelement element = doc.createelement ("NodeName");
3). Add the element node to the root node: root. AppendChild (Element);
4). Create element text: Qdomtext nodetext=doc.createtextnode ("text");
5). add element text to element node: element. AppendChild (Nodetext);
In this project, suppose that the attributes of a note are ordinal, first name, content, font, size, color, weight, italic, underline, and then add a note node to the file as follows:
Qdomdocument Doc;
instruction = doc.createprocessinginstruction ("xml", "Version=\" 1.0\ "encoding=\" utf-8\ "");
Doc.appendchild (instruction);
Qdomelement root = Doc.createelement ("Notes");
Doc.appendchild (root);
Qdomelement Note = doc.createelement ("note");
Root.appendchild (note);
Qdomelement no = doc.createelement ("no");
Note.appendchild (no);
...
...
Qdomtext No_text = Doc.createtextnode ("001");
...
...
You get a note node and save it to the Test.xml file with the following code:
QFile file ("Test.xml");
if (!file.open (qiodevice::writeonly | Qiodevice::truncate | Qiodevice::text))
return;
Qtextstream out (&file);
Out.setcodec ("UTF-8");
Doc.save (Out,4,qdomnode::encodingfromtextstream);
File.close ();
The Test.xml file:
<?xml version= "1.0" encoding= "UTF-8"?>
<Notes>
<note>
<no>001</no>
<name>2010-05-10 (13:53:24) </name>
<CONTENT>A meeting. </content>
<font>script MT bold</font>
<fontSize>16</fontSize>
<color> #00ffff </color>
<weight>0</weight>
<fontItalic>true</fontItalic>
<fontUnderline>true</fontUnderline>
</note>
</Notes>
Above is to create a note node, to continue to add note nodes, you need to add a new node after the existing node, and rewrite into the XML file.
2. To read the node information in an XML document when loading and locating a note, the DOM is implemented by taking the entire document as an object to be loaded into memory for processing, and then the developer can access each node in the object, each node corresponding to a tag in the XML file.
The main operations include:
1). Read root node: qdomelement root = Doc.documentelement ();
2). Read the first child node: qdomnode node = Root.firstchild ();
3). Reads the next child node: node = node.nextsibling ();
4). Match node Tag: node.toelement (). TagName () = = "Note"
5). Read node text: no = Childnode.totext (). data ();
The following is the function implementation code that reads the note properties in the project:
void MainWindow::p arseattr (const qdomelement &element)
{
QString No,name,content,font,fontsize,color;
Qdomnode node = Element.firstchild ();
while (!node.isnull ()) {
if (Node.toelement (). TagName () = = "Note") {//Match note node
Parseattr (Node.toelement ());
} else if (Node.toelement (). TagName () = = "No") {//Match attribute No
Qdomnode Childnode = Node.firstchild ();
if (childnode.nodetype () = = Qdomnode::textnode) {
No = Childnode.totext (). data ();
}
}
else if (node.toelement (). TagName () = = "Name")//Match property name
...
...
node = node.nextsibling ();//Read sibling node
}
}
3. When deleting a note, to delete the corresponding XML node, the main function used is: root.removechild (node); However, after you delete a node, you overwrite the entire file.
The above rewrite of the XML file is necessary, so add qiodevice::truncate in the way the file is opened, which means overwrite overrides. There is no way to directly modify the file, but if the file is very large, you must consider the corresponding efficiency problem.
Since this project requires all notes to be loaded into memory at startup, it is appropriate to use the DOM method, but if the XML file being processed is large and does not need to be read all to memory, it can be implemented in sax, which reads the document into memory by stages, and when it encounters a label or Other stage, You can call the developer's pre-designed callback function to handle it, which is more efficient than the DOM way.