KD SOAP API Documentation  2.2
KDSoapMessageWriter.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Soap project.
4 **
5 ** SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
11 #include "KDSoapMessageWriter_p.h"
12 #include "KDSoapNamespaceManager.h"
14 #include "KDSoapValue.h"
15 #include <QDebug>
16 #include <QVariant>
17 
19  : m_version(KDSoap::SOAP1_1)
20 {
21 }
22 
24 {
25  m_version = version;
26 }
27 
29 {
30  m_messageNamespace = ns;
31 }
32 
33 QByteArray KDSoapMessageWriter::messageToXml(const KDSoapMessage &message, const QString &method, const KDSoapHeaders &headers,
34  const QMap<QString, KDSoapMessage> &persistentHeaders, const KDSoapAuthentication &authentication) const
35 {
36  QByteArray data;
37  QXmlStreamWriter writer(&data);
38  writer.writeStartDocument();
39 
40  KDSoapNamespacePrefixes namespacePrefixes;
41  namespacePrefixes.writeStandardNamespaces(writer, m_version, message.hasMessageAddressingProperties(),
43 
44  QString soapEnvelope;
45  QString soapEncoding;
46  if (m_version == KDSoap::SOAP1_1) {
47  soapEnvelope = KDSoapNamespaceManager::soapEnvelope();
48  soapEncoding = KDSoapNamespaceManager::soapEncoding();
49  } else if (m_version == KDSoap::SOAP1_2) {
52  }
53 
54  writer.writeStartElement(soapEnvelope, QLatin1String("Envelope"));
55 
56  // This has been removed, see https://msdn.microsoft.com/en-us/library/ms995710.aspx for details
57  // writer.writeAttribute(soapEnvelope, QLatin1String("encodingStyle"), soapEncoding);
58 
59  QString messageNamespace = m_messageNamespace;
60  if (!message.namespaceUri().isEmpty() && messageNamespace != message.namespaceUri()) {
61  messageNamespace = message.namespaceUri();
62  }
63 
64  if (!headers.isEmpty() || !persistentHeaders.isEmpty() || message.hasMessageAddressingProperties() || authentication.hasWSUsernameTokenHeader()) {
65  // This writeNamespace line adds the xmlns:n1 to <Envelope>, which looks ugly and unusual (and breaks all unittests)
66  // However it's the best solution in case of headers, otherwise we get n1 in the header and n2 in the body,
67  // and xsi:type attributes that refer to n1, which isn't defined in the body...
68  namespacePrefixes.writeNamespace(writer, messageNamespace, QLatin1String("n1") /*make configurable?*/);
69  writer.writeStartElement(soapEnvelope, QLatin1String("Header"));
70  for (const KDSoapMessage &header : qAsConst(persistentHeaders)) {
71  header.writeChildren(namespacePrefixes, writer, header.use(), messageNamespace, true);
72  }
73  for (const KDSoapMessage &header : qAsConst(headers)) {
74  header.writeChildren(namespacePrefixes, writer, header.use(), messageNamespace, true);
75  }
76  if (message.hasMessageAddressingProperties()) {
77  message.messageAddressingProperties().writeMessageAddressingProperties(namespacePrefixes, writer, messageNamespace, true);
78  }
79  if (authentication.hasWSUsernameTokenHeader()) {
80  authentication.writeWSUsernameTokenHeader(writer);
81  }
82  writer.writeEndElement(); // Header
83  } else {
84  // So in the standard case (no headers) we just rely on Qt calling it n1 and insert it into the map.
85  // Calling this after the writeStartElement(ns, elementName) below leads to a double-definition of n1.
86  namespacePrefixes.insert(messageNamespace, QString::fromLatin1("n1"));
87  }
88 
89  writer.writeStartElement(soapEnvelope, QLatin1String("Body"));
90 
91  const QString elementName = !method.isEmpty() ? method : message.name();
92  if (elementName.isEmpty()) {
93  if (message.isNil()) {
94  // null message, ok (e.g. no arguments, in document/literal mode)
95  } else {
96  qWarning("ERROR: Non-empty message with an empty name!");
97  qDebug() << message;
98  }
99  } else {
100  // Note that the message itself is always qualified.
101  // isQualified() is only for child elements.
102  if (!message.isFault()) {
103  writer.writeStartElement(messageNamespace, elementName);
104  } else {
105  // Fault element should be inside soap namespace
106  writer.writeStartElement(soapEnvelope, elementName);
107  }
108  message.writeElementContents(namespacePrefixes, writer, message.use(), messageNamespace);
109  writer.writeEndElement();
110  }
111  writer.writeEndElement(); // Body
112  writer.writeEndElement(); // Envelope
113  writer.writeEndDocument();
114 
115  return data;
116 }
KDSoapAddressingNamespace addressingNamespace() const
QByteArray messageToXml(const KDSoapMessage &message, const QString &method, const KDSoapHeaders &headers, const QMap< QString, KDSoapMessage > &persistentHeaders, const KDSoapAuthentication &authentication=KDSoapAuthentication()) const
void setMessageNamespace(const QString &ns)
void setVersion(KDSoap::SoapVersion version)
Use use() const
bool isFault() const
bool hasMessageAddressingProperties() const
KDSoapMessageAddressingProperties messageAddressingProperties() const
void writeStandardNamespaces(QXmlStreamWriter &writer, KDSoap::SoapVersion version=KDSoap::SOAP1_1, bool messageAddressingEnabled=false, KDSoapMessageAddressingProperties::KDSoapAddressingNamespace messageAddressingNamespace=KDSoapMessageAddressingProperties::Addressing200508)
void writeNamespace(QXmlStreamWriter &writer, const QString &ns, const QString &prefix)
QString namespaceUri() const
QString name() const
Definition: KDSoapValue.cpp:94
bool isNil() const
Definition: KDSoapValue.cpp:84
@ SOAP1_1
Definition: KDSoapValue.h:42
@ SOAP1_2
Definition: KDSoapValue.h:44

© 2010-2024 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-soap/
Generated by doxygen 1.9.1