summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/examples/qxmlstreambookmarks.qdoc13
-rw-r--r--examples/network/googlesuggest/googlesuggest.cpp7
-rw-r--r--examples/xml/streambookmarks/xbelreader.cpp107
-rw-r--r--examples/xml/streambookmarks/xbelreader.h1
-rw-r--r--src/corelib/xml/qxmlstream.cpp49
-rw-r--r--src/corelib/xml/qxmlstream.h3
-rw-r--r--tests/auto/qxmlstream/tst_qxmlstream.cpp19
7 files changed, 114 insertions, 85 deletions
diff --git a/doc/src/examples/qxmlstreambookmarks.qdoc b/doc/src/examples/qxmlstreambookmarks.qdoc
index def4c47ee9..26964c49df 100644
--- a/doc/src/examples/qxmlstreambookmarks.qdoc
+++ b/doc/src/examples/qxmlstreambookmarks.qdoc
@@ -106,19 +106,18 @@
of reading only takes place if the file is a valid XBEL 1.0 file.
Note that the XML input needs to be well-formed to be accepted by
QXmlStreamReader. Otherwise, the \l{QXmlStreamReader::raiseError()}
- {raiseError()} function is used to display an error message.
+ {raiseError()} function is used to display an error message. Since the
+ XBEL reader is only concerned with reading XML elements, it makes
+ extensive use of the \l{QXmlStreamReader::readNextStartElement()}
+ convenience function.
\snippet examples/xml/streambookmarks/xbelreader.cpp 1
- The \c readUnknownElement() function reads an unknown element. The
- Q_ASSERT() macro is used to provide a pre-condition for the function.
-
- \snippet examples/xml/streambookmarks/xbelreader.cpp 2
-
The \c readXBEL() function reads the name of a startElement and calls
the appropriate function to read it, depending on whether if its a
"folder", "bookmark" or "separator". Otherwise, it calls
- \c readUnknownElement().
+ \l{QXmlStreamReader::skipCurrentElement()}. The Q_ASSERT() macro is used
+ to provide a pre-condition for the function.
\snippet examples/xml/streambookmarks/xbelreader.cpp 3
diff --git a/examples/network/googlesuggest/googlesuggest.cpp b/examples/network/googlesuggest/googlesuggest.cpp
index ada0edfd91..4142511111 100644
--- a/examples/network/googlesuggest/googlesuggest.cpp
+++ b/examples/network/googlesuggest/googlesuggest.cpp
@@ -134,7 +134,6 @@ bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev)
void GSuggestCompletion::showCompletion(const QStringList &choices, const QStringList &hits)
{
-
if (choices.isEmpty() || choices.count() != hits.count())
return;
@@ -204,16 +203,16 @@ void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply)
QXmlStreamReader xml(response);
while (!xml.atEnd()) {
xml.readNext();
- if (xml.tokenType() == QXmlStreamReader::StartElement)
+ if (xml.isStartElement()) {
if (xml.name() == "suggestion") {
QStringRef str = xml.attributes().value("data");
choices << str.toString();
}
- if (xml.tokenType() == QXmlStreamReader::StartElement)
- if (xml.name() == "num_queries") {
+ else if (xml.name() == "num_queries") {
QStringRef str = xml.attributes().value("int");
hits << str.toString();
}
+ }
}
showCompletion(choices, hits);
diff --git a/examples/xml/streambookmarks/xbelreader.cpp b/examples/xml/streambookmarks/xbelreader.cpp
index 47c8c3d269..729fcf8f23 100644
--- a/examples/xml/streambookmarks/xbelreader.cpp
+++ b/examples/xml/streambookmarks/xbelreader.cpp
@@ -62,59 +62,31 @@ bool XbelReader::read(QIODevice *device)
{
setDevice(device);
- while (!atEnd()) {
- readNext();
-
- if (isStartElement()) {
- if (name() == "xbel" && attributes().value("version") == "1.0")
- readXBEL();
- else
- raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
- }
+ if (readNextStartElement()) {
+ if (name() == "xbel" && attributes().value("version") == "1.0")
+ readXBEL();
+ else
+ raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
}
return !error();
}
//! [1]
-//! [2]
-void XbelReader::readUnknownElement()
-{
- Q_ASSERT(isStartElement());
-
- while (!atEnd()) {
- readNext();
-
- if (isEndElement())
- break;
-
- if (isStartElement())
- readUnknownElement();
- }
-}
-//! [2]
-
//! [3]
void XbelReader::readXBEL()
{
Q_ASSERT(isStartElement() && name() == "xbel");
- while (!atEnd()) {
- readNext();
-
- if (isEndElement())
- break;
-
- if (isStartElement()) {
- if (name() == "folder")
- readFolder(0);
- else if (name() == "bookmark")
- readBookmark(0);
- else if (name() == "separator")
- readSeparator(0);
- else
- readUnknownElement();
- }
+ while (readNextStartElement()) {
+ if (name() == "folder")
+ readFolder(0);
+ else if (name() == "bookmark")
+ readBookmark(0);
+ else if (name() == "separator")
+ readSeparator(0);
+ else
+ readUnknownElement();
}
}
//! [3]
@@ -132,10 +104,12 @@ void XbelReader::readTitle(QTreeWidgetItem *item)
//! [5]
void XbelReader::readSeparator(QTreeWidgetItem *item)
{
+ Q_ASSERT(isStartElement() && name() == "separator");
+
QTreeWidgetItem *separator = createChildItem(item);
separator->setFlags(item->flags() & ~Qt::ItemIsSelectable);
separator->setText(0, QString(30, 0xB7));
- readElementText();
+ skipCurrentElement();
}
//! [5]
@@ -147,24 +121,17 @@ void XbelReader::readFolder(QTreeWidgetItem *item)
bool folded = (attributes().value("folded") != "no");
treeWidget->setItemExpanded(folder, !folded);
- while (!atEnd()) {
- readNext();
-
- if (isEndElement())
- break;
-
- if (isStartElement()) {
- if (name() == "title")
- readTitle(folder);
- else if (name() == "folder")
- readFolder(folder);
- else if (name() == "bookmark")
- readBookmark(folder);
- else if (name() == "separator")
- readSeparator(folder);
- else
- readUnknownElement();
- }
+ while (readNextStartElement()) {
+ if (name() == "title")
+ readTitle(folder);
+ else if (name() == "folder")
+ readFolder(folder);
+ else if (name() == "bookmark")
+ readBookmark(folder);
+ else if (name() == "separator")
+ readSeparator(folder);
+ else
+ skipCurrentElement();
}
}
@@ -177,18 +144,12 @@ void XbelReader::readBookmark(QTreeWidgetItem *item)
bookmark->setIcon(0, bookmarkIcon);
bookmark->setText(0, QObject::tr("Unknown title"));
bookmark->setText(1, attributes().value("href").toString());
- while (!atEnd()) {
- readNext();
-
- if (isEndElement())
- break;
-
- if (isStartElement()) {
- if (name() == "title")
- readTitle(bookmark);
- else
- readUnknownElement();
- }
+
+ while (readNextStartElement()) {
+ if (name() == "title")
+ readTitle(bookmark);
+ else
+ skipCurrentElement();
}
}
diff --git a/examples/xml/streambookmarks/xbelreader.h b/examples/xml/streambookmarks/xbelreader.h
index 80f0a28650..2debadce3d 100644
--- a/examples/xml/streambookmarks/xbelreader.h
+++ b/examples/xml/streambookmarks/xbelreader.h
@@ -62,7 +62,6 @@ public:
private:
//! [2]
- void readUnknownElement();
void readXBEL();
void readTitle(QTreeWidgetItem *item);
void readSeparator(QTreeWidgetItem *item);
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index a08b167018..8b2462e229 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -622,6 +622,55 @@ QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
return d->type;
}
+/*!
+ Reads until the next start element within the current element. Returns true
+ when a start element was reached. When the end element was reached, or when
+ an error occurred, false is returned.
+
+ The current element is the element matching the most recently parsed start
+ element of which a matching end element has not yet been reached. When the
+ parser has reached the end element, the current element becomes the parent
+ element.
+
+ This is a convenience function for when you're only concerned with parsing
+ XML elements. The \l{QXmlStream Bookmarks Example} makes extensive use of
+ this function.
+
+ \since 4.6
+ */
+bool QXmlStreamReader::readNextStartElement()
+{
+ while (readNext() != Invalid) {
+ if (isEndElement())
+ return false;
+ else if (isStartElement())
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Reads until the end of the current element, skipping any child nodes.
+ This function is useful for skipping unknown elements.
+
+ The current element is the element matching the most recently parsed start
+ element of which a matching end element has not yet been reached. When the
+ parser has reached the end element, the current element becomes the parent
+ element.
+
+ \since 4.6
+ */
+void QXmlStreamReader::skipCurrentElement()
+{
+ int depth = 1;
+ while (depth && readNext() != Invalid) {
+ if (isEndElement())
+ --depth;
+ else if (isStartElement())
+ ++depth;
+ }
+}
+
/*
* Use the following Perl script to generate the error string index list:
===== PERL SCRIPT ====
diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/xml/qxmlstream.h
index 420a66ad3e..21dcb404e8 100644
--- a/src/corelib/xml/qxmlstream.h
+++ b/src/corelib/xml/qxmlstream.h
@@ -321,6 +321,9 @@ public:
bool atEnd() const;
TokenType readNext();
+ bool readNextStartElement();
+ void skipCurrentElement();
+
TokenType tokenType() const;
QString tokenString() const;
diff --git a/tests/auto/qxmlstream/tst_qxmlstream.cpp b/tests/auto/qxmlstream/tst_qxmlstream.cpp
index 375528c323..f496dcf1a1 100644
--- a/tests/auto/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/qxmlstream/tst_qxmlstream.cpp
@@ -550,6 +550,7 @@ private slots:
void setEntityResolver();
void readFromQBuffer() const;
void readFromQBufferInvalid() const;
+ void readNextStartElement() const;
void crashInUTF16Codec() const;
void hasAttributeSignature() const;
void hasAttribute() const;
@@ -1107,6 +1108,24 @@ void tst_QXmlStream::readFromQBufferInvalid() const
QVERIFY(reader.hasError());
}
+void tst_QXmlStream::readNextStartElement() const
+{
+ QLatin1String in("<?xml version=\"1.0\"?><A><!-- blah --><B><C/></B><B attr=\"value\"/>text</A>");
+ QXmlStreamReader reader(in);
+
+ QVERIFY(reader.readNextStartElement());
+ QVERIFY(reader.isStartElement() && reader.name() == "A");
+
+ int amountOfB = 0;
+ while (reader.readNextStartElement()) {
+ QVERIFY(reader.isStartElement() && reader.name() == "B");
+ ++amountOfB;
+ reader.skipCurrentElement();
+ }
+
+ QCOMPARE(amountOfB, 2);
+}
+
void tst_QXmlStream::crashInUTF16Codec() const
{
QEventLoop eventLoop;