0

I was trying to loop through all children of specific XML node and join their name attributes. The structure:

<params>
    <param name="BLAH" />
</params>

The desired result:

PARAM1='$PARAM1',PARAM2='$PARAM2',PARAM3='$PARAM3'[...]

The code:

    // Create empty text stream
    QTextStream paramNames("");
    // Start looping child by child
    QDomElement child = params.firstChildElement();
    bool firstIteration = true;
    while( !child.isNull() ) {  
        QString param_name = child.attribute("n");
        // Skips empty names
        if(param_name.length()>0) {
          // This prevents both leading and trailing comma
          if(!firstIteration)
              paramNames<<",";
          else
              firstIteration = false;
          // This should fill in one entry
          paramNames<<param_name<<"='$"<<param_name<<'\'';
        }
        child = child.nextSiblingElement();
    }

Now even the debugger says that if I do

QString paramNamesSTR = paramNames.readAll();

the paramNamesSTR is an empty string. However if I use std library instead, everything works:

    std::stringstream paramNames("");
    QDomElement child = params.firstChildElement();
    bool firstIteration = true;
    while( !child.isNull() ) {  
        std::string param_name = child.attribute("n").toUtf8().constData();
        if(param_name.length()>0) {
          if(!firstIteration)
              paramNames<<",";
          else
              firstIteration = false;
          paramNames<<param_name<<"='$"<<param_name<<'\'';
        }
        child = child.nextSiblingElement();
    }
    QString paramNamesSTR = QString::fromStdString( paramNames.str() );

So what's the difference? Why does the Qt QTextStream return empty string? I would really prefer to be consistent with used libraries and therefore use the QTextStream rather than std::stringstream, although presonally, I prefer the former.

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778

1 Answers1

3

To be able to use QTextStream you need to pass it something to operate on (the stream itself doesn't store any data, it just operates on a string or iodevice). Passing it a string literal is not the right thing to do. The difference is when you create the std::stringstream and pass it a string literal, an underlying stream buffer is created automatically, and that literal is used as the buffer's initial value. In case of QTextStream, that created a read-only stream that contains the passed literal. The right way to create a QTextStream would be to create the buffer first, and then create the stream to operate on that buffer, for example:

QString string; //you can also use a QByteArray, or any QIODevice
QTextStream stream(&string);
SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
  • And do I access the stream full value using that original `QString`, or do I still call `readAll`? If it saves data in `QString`, ins't it just as good as using `QString`'s `operator+`? – Tomáš Zato Oct 05 '15 at 11:31
  • @TomášZato, you can do it either way. – SingerOfTheFall Oct 05 '15 at 11:32
  • I tested the code and it does work, so thanks. However I'm little but unsire whether I should even bother with `TextStream` when it behaves just as if I just used `+` to join the strings... – Tomáš Zato Oct 05 '15 at 11:35
  • @TomášZato, QTextStream has `>>` operators, padding, and other stuff which QString lacks. However if you are only accumulating string data and do not require any of those, you might as well use QString. QString's `operator+` is really fast because QString preallocates space in a special way, so performance should not be a problem. – SingerOfTheFall Oct 05 '15 at 11:35