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 }