diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 9dcdf490412..50f87900161 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -2913,6 +2913,8 @@ public:
uint hasIoError :1;
uint hasEncodingError :1;
uint autoFormatting :1;
+ uint didWriteStartDocument :1;
+ uint didWriteAnyToken :1;
std::string autoFormattingIndent;
NamespaceDeclaration emptyNamespace;
qsizetype lastNamespaceDeclaration;
@@ -2946,6 +2948,8 @@ QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
lastNamespaceDeclaration = 1;
autoFormatting = false;
namespacePrefixCount = 0;
+ didWriteStartDocument = false;
+ didWriteAnyToken = false;
}
void QXmlStreamWriterPrivate::write(QAnyStringView s)
@@ -3065,6 +3069,7 @@ void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclarati
write(namespaceDeclaration.namespaceUri);
write("\"");
}
+ didWriteAnyToken = true;
}
bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
@@ -3084,6 +3089,7 @@ bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
}
inStartElement = inEmptyElement = false;
lastNamespaceDeclaration = namespaceDeclarations.size();
+ didWriteAnyToken = true;
return hadSomethingWritten;
}
@@ -3149,7 +3155,8 @@ QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNa
void QXmlStreamWriterPrivate::indent(int level)
{
- write("\n");
+ if (didWriteStartDocument || didWriteAnyToken)
+ write("\n");
for (int i = 0; i < level; ++i)
write(autoFormattingIndent);
}
@@ -3375,6 +3382,7 @@ void QXmlStreamWriter::writeAttribute(QAnyStringView qualifiedName, QAnyStringVi
d->write("=\"");
d->writeEscaped(value, true);
d->write("\"");
+ d->didWriteAnyToken = true;
}
/*! Writes an attribute with \a name and \a value, prefixed for
@@ -3403,6 +3411,7 @@ void QXmlStreamWriter::writeAttribute(QAnyStringView namespaceUri, QAnyStringVie
d->write("=\"");
d->writeEscaped(value, true);
d->write("\"");
+ d->didWriteAnyToken = true;
}
/*!
@@ -3610,7 +3619,8 @@ void QXmlStreamWriter::writeEndDocument()
Q_D(QXmlStreamWriter);
while (d->tagStack.size())
writeEndElement();
- d->write("\n");
+ if (d->didWriteStartDocument || d->didWriteAnyToken)
+ d->write("\n");
}
/*!
@@ -3621,6 +3631,7 @@ void QXmlStreamWriter::writeEndDocument()
void QXmlStreamWriter::writeEndElement()
{
Q_D(QXmlStreamWriter);
+ Q_ASSERT(d->didWriteAnyToken);
if (d->tagStack.isEmpty())
return;
@@ -3744,6 +3755,7 @@ void QXmlStreamWriter::writeProcessingInstruction(QAnyStringView target, QAnyStr
d->write(data);
}
d->write("?>");
+ d->didWriteAnyToken = true;
}
@@ -3778,6 +3790,7 @@ void QXmlStreamWriter::writeStartDocument(QAnyStringView version)
if (d->device) // stringDevice does not get any encoding
d->write("\" encoding=\"UTF-8");
d->write("\"?>");
+ d->didWriteStartDocument = true;
}
/*! Writes a document start with the XML version number \a version
@@ -3801,6 +3814,7 @@ void QXmlStreamWriter::writeStartDocument(QAnyStringView version, bool standalon
d->write("\" standalone=\"yes\"?>");
else
d->write("\" standalone=\"no\"?>");
+ d->didWriteStartDocument = true;
}
@@ -3862,6 +3876,7 @@ void QXmlStreamWriterPrivate::writeStartElement(QAnyStringView namespaceUri, QAn
writeNamespaceDeclaration(namespaceDeclarations[i]);
}
tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
+ didWriteAnyToken = true;
}
/*! Writes the current state of the \a reader. All possible valid
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
index b90d05b0fa1..d40cb8fa8d0 100644
--- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
@@ -559,6 +559,10 @@ private slots:
void writerAutoFormattingWithProcessingInstructions() const;
void writerAutoEmptyTags() const;
void writeAttributesWithSpace() const;
+ void writerAutoFormattingProcessingInstructionFirst() const;
+ void writerAutoFormattingStartElementFirst() const;
+ void writerAutoFormattingCommentFirst() const;
+ void writerAutoFormattingNamespaceFirst() const;
void addExtraNamespaceDeclarations();
void setEntityResolver();
void readFromQBuffer() const;
@@ -1075,6 +1079,74 @@ void tst_QXmlStream::writeAttributesWithSpace() const
QCOMPARE(buffer.buffer().data(), s.toUtf8().data());
}
+void tst_QXmlStream::writerAutoFormattingProcessingInstructionFirst() const
+{
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QXmlStreamWriter writer(&buffer);
+ writer.setAutoFormatting(true);
+ writer.writeProcessingInstruction("B");
+ writer.writeComment("This is a comment");
+ writer.writeStartElement("A");
+ writer.writeNamespace("http://website.com", "website");
+ writer.writeDefaultNamespace("http://websiteNo2.com");
+ writer.writeEndElement();
+ writer.writeEndDocument();
+ const char *str =
+ "\n\n\n";
+ QCOMPARE(buffer.buffer().data(), str);
+}
+void tst_QXmlStream::writerAutoFormattingStartElementFirst() const
+{
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QXmlStreamWriter writer(&buffer);
+ writer.setAutoFormatting(true);
+ writer.writeStartElement("A");
+ writer.writeNamespace("http://website.com", "website");
+ writer.writeComment("This is a comment");
+ writer.writeProcessingInstruction("B");
+ writer.writeDefaultNamespace("http://websiteNo2.com");
+ writer.writeEndElement();
+ writer.writeEndDocument();
+ const char *str = "\n \n \n\n";
+ QCOMPARE(buffer.buffer().data(), str);
+}
+
+void tst_QXmlStream::writerAutoFormattingCommentFirst() const
+{
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QXmlStreamWriter writer(&buffer);
+ writer.setAutoFormatting(true);
+ writer.writeComment("This is a comment");
+ writer.writeStartElement("A");
+ writer.writeNamespace("http://website.com", "website");
+ writer.writeEndElement();
+ writer.writeDefaultNamespace("http://websiteNo2.com");
+ writer.writeProcessingInstruction("B");
+ writer.writeEndDocument();
+ const char *str = "\n\n";
+ QCOMPARE(buffer.buffer().data(), str);
+}
+
+void tst_QXmlStream::writerAutoFormattingNamespaceFirst() const
+{
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QXmlStreamWriter writer(&buffer);
+ writer.setAutoFormatting(true);
+ writer.writeNamespace("http://website.com", "website");
+ writer.writeStartElement("A");
+ writer.writeDefaultNamespace("http://websiteNo2.com");
+ writer.writeProcessingInstruction("B");
+ writer.writeEndElement();
+ writer.writeComment("This is a comment");
+ writer.writeEndDocument();
+ const char *str = "\n \n\n";
+ QCOMPARE(buffer.buffer().data(), str);
+}
+
void tst_QXmlStream::writerAutoEmptyTags() const
{
QBuffer buffer;