Vishal Kotcherlakota
Vishal Kotcherlakota

Reputation: 1154

How do I stop QXmlStreamWriter from escaping quotation marks?

Let me begin by expressing my understanding that what I'm trying to do is not normal, nor is it typically well advised. I'm fully aware that in normal XML, the " character is reserved.

I'm generating .vcxproj files to use in Visual Studio 2010, using a Qt application. I'm taking advantage of the QXmlStreamWriter class to write the XML needed for the project file. However, I'm running into a problem due to Microsoft's non-compliance with the XML standard.

In CustomBuild elements, the user needs to specify the command for building the file. In the case of Qt projects within Visual Studio, you end up with something like this:

  <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o "..\myproj\moc_%(Filename).cpp"  -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_XML_LIB -DQT_SQL_LIB -DQT_OPENGL_LIB -DQT_QT3SUPPORT_LIB -DQT3_SUPPORT -DQT_SVG_LIB "-I." "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtXml" "-I$(QTDIR)\include\QtSql" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\Qt3Support" "-I$(QTDIR)\include\QtSvg" "-I$(QTDIR)\include\QtTest" "-I..\myproj"</Command>

Yucky, but c'est la vie, especially with Microsoft. Unfortunatey, my QXmlStreamWriter object produces this (fully compliant) output:

  <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe&quot; &quot;%(FullPath)&quot; -o &quot;..\myproj\moc_%(Filename).cpp&quot;   -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_XML_LIB -DQT_SQL_LIB -DQT_OPENGL_LIB -DQT_QT3SUPPORT_LIB -DQT3_SUPPORT -DQT_SVG_LIB &quot;-I.&quot; &quot;-I$(QTDIR)\include&quot; &quot;-I$(QTDIR)\include\QtCore&quot; &quot;-I$(QTDIR)\include\QtGui&quot; &quot;-I$(QTDIR)\include\QtXml&quot; &quot;-I$(QTDIR)\include\QtSql&quot; &quot;-I$(QTDIR)\include\QtOpenGL&quot; &quot;-I$(QTDIR)\include\Qt3Support&quot; &quot;-I$(QTDIR)\include\QtSvg&quot; &quot;-I$(QTDIR)\include\QtTest&quot; &quot;..\myproj&quot;</Command>

Naturally, Visual Studio isn't impressed. What are my options here? I could probably read back the file and un-escape it, but that doesn't sound particularly efficient or intelligent.

Upvotes: 4

Views: 1181

Answers (2)

Vishal Kotcherlakota
Vishal Kotcherlakota

Reputation: 1154

Bypassing straight to the QIODevice the way @rohanpm suggested was the way to go.

I subclassed QXmlStreamWriter and added a method to write quoted strings.

customstreamwriter.h

#ifndef CUSTOMSTREAMWRITER_H
#define CUSTOMSTREAMWRITER_H

#include <QXmlStreamWriter>

class CustomStreamWriter : public QXmlStreamWriter
{
public:
    CustomStreamWriter(QIODevice *device);
    void writeQuotedCharacters(QString text);
};

#endif // CUSTOMSTREAMWRITER_H

customstreamwriter.cpp

#include "customstreamwriter.h"

CustomStreamWriter::CustomStreamWriter(QIODevice *device) :
    QXmlStreamWriter(device)
{
}

void CustomStreamWriter::writeQuotedCharacters(QString text) {
    QStringList parts = text.split('"');
    while (!parts.isEmpty()) {
        QString part = parts.takeFirst();
        writeCharacters(part);
        if (!parts.isEmpty()) {
            device()->putChar('"');
        }
    }
}

Instead of using QXmlStreamWriter, I use my CustomStreamWriter instead. The only difference is that when I need to write a quoted string, I call my writeQuotedCharacters() method.

Upvotes: 1

rohanpm
rohanpm

Reputation: 4274

I guess you are using QXmlStreamWriter::writeCharacters or similar to write the strings which contain " ?

Perhaps, before calling that function, you could check if the string you are about to write contains ". If it does, you could split it on ", write the non-" characters via QXmlStreamWriter::writeCharacters, and write " directly to the underlying QIODevice:

QString maybeHasQuotes = ...;
QStringList parts = maybeHasQuotes.split('"');
while (!parts.isEmpty()) {
    QString part = parts.takeFirst();
    writer.writeCharacters(part);
    if (!parts.isEmpty()) {
        writer.device()->putChar('"');
    }
}

Upvotes: 5

Related Questions