How do I use foreach with QDomNodeList in Qt?
Asked Answered
S

2

12

I'm new to Qt and I'm learning something new every day.
Currently, I'm developing a small application for my Nokia N900 in my free time.
Everything is fine, I am able to compile and run Maemo applications on the device.

I've just learned about the foreach keyword in Qt. (I know it is not in C++, so I didn't think about it until I accidentally stumbled upon a Qt doc that mentioned it.)
So, I decided to change my quite annoying and unreadable loops to foreach, but I failed with this:

QDomNodeList list = doc.lastChild().childNodes().at(1).firstChild().childNodes();
for (int x = 0; x < list.count(); x++)
{
    QDomElement node = list.at(x).toElement();
    // Do something with node
}

This is how I tried:

foreach (QDomElement node, doc.lastChild().childNodes().at(1).firstChild().childNodes())
{
    // Do something with node
}

For some reason the above code doesn't even compile. I get cryptic error messages from the compiler.

Could someone please explain to me how to get it right?

If the foreach loop doesn't support QDomNodeList, is there a way to handle XML files which supports foreach?

EDIT:

To clarify, // Do something with node is the following in this case:

EveCharacter chr;
chr.setName(node.attribute(EVE_NAME));
chr.setId(node.attribute(EVE_CHARACTER_ID).toInt());
acc->addCharacter(chr);

Where acc is of type EveAccount, which stores data in a QList<EveCharacter>.

The uppercase symbols are compile-time constant strings.
(I'm creating a client for the EVE Online API. This is from the method that receives the account characters XML and interprets it.)

This is how I create doc:

QDomDocument doc;
doc.setContent(reply->readAll());

Note that reply is a QNetworkReply* which is sent back from a QNetworkAccessManager.

However, as the EVE API works with XML, I do a lot of XML parsing very similar to this in many places in my application.
Most of the XMLs can be several hundred lines long and can contain quite non-regular data patterns, such as this one.

Shotton answered 26/5, 2010 at 15:57 Comment(1)
As an aside, the reason you get a cryptic message is because foreach isn't actually a keyword, it's a macro. Because C++ doesn't support the syntax, Qt has to do some clever pre-processor stuff to make it work. That means that any compiler messages will be for code that doesn't look much like the code as you're seeing it.Interlocutrix
C
9

foreach only supports the container classes, so you cannot use it with a QDomNodeList.

I'm not sure of you actual goal, but I find the QXmlSimpleReader and QXmlStreamReader to be the easiest way to deal with XML.

Edit to match question edit:

What you are trying to do looks like a prime candidate for XPath or XQuery. Take a look at the QtXmlPatterns module this will give you a set of character nodes without having to loop through all the other nodes.

Cussed answered 26/5, 2010 at 16:15 Comment(8)
@Adam - I read the docs you linked, but I failed to understand how to use them properly. I see no methods in them to navigate in the DOM tree. Could you please provide me the equivalent of my code using QXmlSimpleReader and QXmlStreamReader?Shotton
Sure if you provide // Do something with nodeCussed
I'll be more clear. If you are just reading or writing XML files those work great. If you are trying to use XML as a database and don't want to use XQuery or XPath (not sure why you would want to do that), you would need QDomDocument.Cussed
@Adam - I added the code of // Do something with node, and some more explanation about what I need to achieve with it along with some links about what XMLs I need to parse.Shotton
@Adam - Just a side tip: if you begin your post with @Venemo, SO will notify me that I have a new response. :)Shotton
@Shotton - Odd, I get notifications whenever someone responds to something I commented on. Anyways, I would use XPath or XQuery for this. It looks like you just want to pull values out of specific nodes which is what the query languages were designed for: doc.qt.nokia.com/4.6/qtxmlpatterns.htmlCussed
@Adam - Unfortunately, I'm not familiar with XPath nor XQuery. Still, thank you for pointing out all those options - I definitely will learn them sometime in the future.Shotton
QXMLStreamReader and QXMLSimpleReader can't deal with 'almost right' xml-files, where you have one-level tags in different orderOctopus
I
2

foreach works with Qt Generic Containers. It doesn't look like QDomNodeList inherits from anything, so you can't use foreach.

Could you iterate through the node list and insert the nodes into a QList<QDomElement>?

Interlocutrix answered 26/5, 2010 at 16:6 Comment(3)
Any reason you link to the 4.2 docs for containers but the 4.6 docs for the class? :)Cussed
@Adam - I changed it soon after I posted - It's just what Google brings up! I find which docs you get to with the first result on Google are pretty arbitrary...Interlocutrix
@Shotton - fair enough. Well, you'll just have to use one ugly loop then.Interlocutrix

© 2022 - 2024 — McMap. All rights reserved.