summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization/qxmlstream.cpp
diff options
context:
space:
mode:
authorMagdalena Stojek <magdalena.stojek@qt.io>2025-03-13 13:38:30 +0100
committerMagdalena Stojek <magdalena.stojek@qt.io>2025-03-19 07:31:15 +0100
commitc3295bd59cb1c3b858b6a858aba4481adeea209b (patch)
tree2a03796b2a81b820b660922db3f074c1f65903a2 /src/corelib/serialization/qxmlstream.cpp
parentd359035c804021f59da70a75d962bfeafd320a71 (diff)
QXmlStreamWriter: Ensure correct newline handling with auto-formatting
Previously, QXmlStreamWriter would incorrectly insert a newline before the first token when writeStartDocument() was not used, while auto-formatting was enabled. This fix ensures that the first token is written inline without an extra leading newline, while preserving expected formatting for subsequent tokens. To achieve this, two new flags have been introduced: - didWriteStartDocument: Tracks whether writeStartDocument() was called. - didWriteAnyToken: Ensures that at least one token has been written before allowing newlines. Fixes: QTBUG-28721 Pick-to: 6.9 6.8 Change-Id: I8be7e8fc6ac0e63304359d24c6c8372e5ba42bb4 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/serialization/qxmlstream.cpp')
-rw-r--r--src/corelib/serialization/qxmlstream.cpp19
1 files changed, 17 insertions, 2 deletions
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