File indexing completed on 2024-12-08 10:16:04

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "xmlwriter.h"
0008 #include "datatypes.h"
0009 #include "element.h"
0010 
0011 #include <QXmlStreamWriter>
0012 
0013 using namespace OSM;
0014 
0015 template <typename T>
0016 static void writeTags(QXmlStreamWriter &writer, const T &elem)
0017 {
0018     for (const auto &tag : elem.tags) {
0019         writer.writeStartElement(QStringLiteral("tag"));
0020         writer.writeAttribute(QStringLiteral("k"), QString::fromUtf8(tag.key.name()));
0021         writer.writeAttribute(QStringLiteral("v"), QString::fromUtf8(tag.value));
0022         writer.writeEndElement();
0023     }
0024 }
0025 
0026 void XmlWriter::writeToIODevice(const DataSet &dataSet, QIODevice *out)
0027 {
0028     QXmlStreamWriter writer(out);
0029     writer.setAutoFormatting(true);
0030     writer.setAutoFormattingIndent(-1);
0031 
0032     writer.writeStartDocument();
0033     // using \123 instead of 'S' here prevents reuse lint from interpreting the following string as a license header for this file
0034     writer.writeComment(QStringLiteral("\n    \123PDX-FileCopyrightText: OpenStreetMap contributors\n    \123PDX-License-Identifier: ODbL-1.0\n"));
0035     writer.writeStartElement(QStringLiteral("osm"));
0036     writer.writeAttribute(QStringLiteral("version"), QStringLiteral("0.6"));
0037     writer.writeAttribute(QStringLiteral("generator"), QStringLiteral("KOSM"));
0038 
0039     OSM::BoundingBox bbox;
0040     OSM::for_each(dataSet, [&bbox](auto elem) { bbox = OSM::unite(bbox, elem.boundingBox()); });
0041     writer.writeStartElement(QStringLiteral("bounds"));
0042     writer.writeAttribute(QStringLiteral("minlat"), QString::number(bbox.min.latF(), 'f', 10));;
0043     writer.writeAttribute(QStringLiteral("minlon"), QString::number(bbox.min.lonF(), 'f', 10));;
0044     writer.writeAttribute(QStringLiteral("maxlat"), QString::number(bbox.max.latF(), 'f', 10));;
0045     writer.writeAttribute(QStringLiteral("maxlon"), QString::number(bbox.max.lonF(), 'f', 10));;
0046     writer.writeEndElement();
0047 
0048     for (const auto &node : dataSet.nodes) {
0049         writer.writeStartElement(QStringLiteral("node"));
0050         writer.writeAttribute(QStringLiteral("id"), QString::number(node.id));
0051         writer.writeAttribute(QStringLiteral("lat"), QString::number(node.coordinate.latF(), 'f', 10));
0052         writer.writeAttribute(QStringLiteral("lon"), QString::number(node.coordinate.lonF(), 'f', 10));
0053         writeTags(writer, node);
0054         writer.writeEndElement();
0055     }
0056 
0057     for (const auto &way : dataSet.ways) {
0058         writer.writeStartElement(QStringLiteral("way"));
0059         writer.writeAttribute(QStringLiteral("id"), QString::number(way.id));
0060         for (const auto &nd : way.nodes) {
0061             writer.writeStartElement(QStringLiteral("nd"));
0062             writer.writeAttribute(QStringLiteral("ref"), QString::number(nd));
0063             writer.writeEndElement();
0064         }
0065         writeTags(writer, way);
0066         writer.writeEndElement();
0067     }
0068 
0069     for (const auto &rel : dataSet.relations) {
0070         writer.writeStartElement(QStringLiteral("relation"));
0071         writer.writeAttribute(QStringLiteral("id"), QString::number(rel.id));
0072         for (const auto &mem : rel.members) {
0073             writer.writeStartElement(QStringLiteral("member"));
0074             switch (mem.type()) {
0075                 case OSM::Type::Null: Q_UNREACHABLE();
0076                 case OSM::Type::Node: writer.writeAttribute(QStringLiteral("type"), QStringLiteral("node")); break;
0077                 case OSM::Type::Way: writer.writeAttribute(QStringLiteral("type"), QStringLiteral("way")); break;
0078                 case OSM::Type::Relation: writer.writeAttribute(QStringLiteral("type"), QStringLiteral("relation")); break;
0079             }
0080             writer.writeAttribute(QStringLiteral("ref"), QString::number(mem.id));
0081             if (!mem.role().isNull()) {
0082                 writer.writeAttribute(QStringLiteral("role"), QString::fromUtf8(mem.role().name()));
0083             }
0084             writer.writeEndElement();
0085         }
0086         writeTags(writer, rel);
0087         writer.writeEndElement();
0088     }
0089 
0090     writer.writeEndElement();
0091     writer.writeEndDocument();
0092 }