KOSMIndoorMap

xmlparser.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "xmlparser.h"
8 #include "datatypes.h"
9 
10 #include <QDebug>
11 #include <QIODevice>
12 #include <QXmlStreamReader>
13 
14 using namespace OSM;
15 
16 XmlParser::XmlParser(DataSet* dataSet)
17  : m_dataSet(dataSet)
18 {
19  assert(dataSet);
20 }
21 
22 void XmlParser::parse(QIODevice *io)
23 {
24  QXmlStreamReader reader(io);
25  while (!reader.atEnd() && !reader.hasError()) {
26  const auto token = reader.readNext();
27  if (token != QXmlStreamReader::StartElement) {
28  continue;
29  }
30 
31  if (reader.name() == QLatin1String("node")) {
32  parseNode(reader);
33  } else if (reader.name() == QLatin1String("way")) {
34  parseWay(reader);
35  } else if (reader.name() == QLatin1String("relation")) {
36  parseRelation(reader);
37  } else if (reader.name() == QLatin1String("remark")) {
38  m_error = reader.readElementText();
39  return;
40  }
41  }
42 
43  if (reader.hasError()) {
44  qDebug() << reader.errorString();
45  }
46 }
47 
48 void XmlParser::parseNode(QXmlStreamReader &reader)
49 {
50  Node node;
51  node.id = reader.attributes().value(QLatin1String("id")).toLongLong();
52  node.coordinate = Coordinate(reader.attributes().value(QLatin1String("lat")).toDouble(), reader.attributes().value(QLatin1String("lon")).toDouble());
53 
54  while (!reader.atEnd() && reader.readNext() != QXmlStreamReader::EndElement) {
55  if (reader.tokenType() != QXmlStreamReader::StartElement) {
56  continue;
57  }
58  if (reader.name() == QLatin1String("tag")) {
59  parseTag(reader, node);
60  }
61  reader.skipCurrentElement();
62  }
63 
64  m_dataSet->addNode(std::move(node));
65 }
66 
67 void XmlParser::parseWay(QXmlStreamReader &reader)
68 {
69  Way way;
70  way.id = reader.attributes().value(QLatin1String("id")).toLongLong();
71 
72  while (!reader.atEnd() && reader.readNext() != QXmlStreamReader::EndElement) {
73  if (reader.tokenType() != QXmlStreamReader::StartElement) {
74  continue;
75  }
76  if (reader.name() == QLatin1String("nd")) {
77  OSM::Id node;
78  node = reader.attributes().value(QLatin1String("ref")).toLongLong();
79  way.nodes.push_back(node);
80  } else if (reader.name() == QLatin1String("tag")) {
81  parseTagOrBounds(reader, way);
82  } else if (reader.name() == QLatin1String("bounds")) {
83  parseBounds(reader, way);
84  }
85  reader.skipCurrentElement();
86  }
87 
88  m_dataSet->addWay(std::move(way));
89 }
90 
91 void XmlParser::parseRelation(QXmlStreamReader &reader)
92 {
93  Relation rel;
94  rel.id = reader.attributes().value(QLatin1String("id")).toLongLong();
95 
96  while (!reader.atEnd() && reader.readNext() != QXmlStreamReader::EndElement) {
97  if (reader.tokenType() != QXmlStreamReader::StartElement) {
98  continue;
99  }
100  if (reader.name() == QLatin1String("tag")) {
101  parseTagOrBounds(reader, rel);
102  } else if (reader.name() == QLatin1String("bounds")) { // Overpass style bounding box
103  parseBounds(reader, rel);
104  } else if (reader.name() == QLatin1String("member")) {
105  Member member;
106  member.id = reader.attributes().value(QLatin1String("ref")).toLongLong();
107  const auto type = reader.attributes().value(QLatin1String("type"));
108  if (type == QLatin1String("node")) {
109  member.setType(Type::Node);
110  } else if (type == QLatin1String("way")) {
111  member.setType(Type::Way);
112  } else {
113  member.setType(Type::Relation);
114  }
115  member.setRole(m_dataSet->makeRole(reader.attributes().value(QLatin1String("role")).toUtf8().constData(), OSM::StringMemory::Transient));
116  rel.members.push_back(std::move(member));
117  }
118  reader.skipCurrentElement();
119  }
120 
121  m_dataSet->addRelation(std::move(rel));
122 }
123 
124 template <typename T>
125 void XmlParser::parseTag(QXmlStreamReader &reader, T &elem)
126 {
127  const auto key = m_dataSet->makeTagKey(reader.attributes().value(QLatin1String("k")).toString().toUtf8().constData(), OSM::StringMemory::Transient);
128  OSM::setTagValue(elem, key, reader.attributes().value(QLatin1String("v")).toUtf8());
129 }
130 
131 template <typename T>
132 void XmlParser::parseTagOrBounds(QXmlStreamReader &reader, T &elem)
133 {
134  if (reader.attributes().value(QLatin1String("k")) == QLatin1String("bBox")) { // osmconvert style bounding box
135  const auto v = reader.attributes().value(QLatin1String("v")).split(QLatin1Char(','));
136  if (v.size() == 4) {
137  elem.bbox.min = Coordinate(v[1].toDouble(), v[0].toDouble());
138  elem.bbox.max = Coordinate(v[3].toDouble(), v[2].toDouble());
139  }
140  } else {
141  parseTag(reader, elem);
142  }
143 }
144 
145 template<typename T>
146 void XmlParser::parseBounds(QXmlStreamReader &reader, T &elem)
147 {
148  // overpass style bounding box
149  elem.bbox.min = Coordinate(reader.attributes().value(QLatin1String("minlat")).toDouble(), reader.attributes().value(QLatin1String("minlon")).toDouble());
150  elem.bbox.max = Coordinate(reader.attributes().value(QLatin1String("maxlat")).toDouble(), reader.attributes().value(QLatin1String("maxlon")).toDouble());
151 }
152 
153 QString XmlParser::error() const
154 {
155  return m_error;
156 }
bool atEnd() const const
QString toString() const const
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
Definition: datatypes.h:37
QStringRef value(const QString &namespaceUri, const QString &name) const const
QByteArray toUtf8() const const
void skipCurrentElement()
void setTagValue(Elem &elem, TagKey key, const QByteArray &value)
Inserts a new tag, or updates an existing one.
Definition: datatypes.h:433
An OSM node.
Definition: datatypes.h:194
const char * constData() const const
qlonglong toLongLong(bool *ok, int base) const const
QXmlStreamReader::TokenType readNext()
QXmlStreamReader::TokenType tokenType() const const
int64_t Id
OSM element identifier.
Definition: datatypes.h:27
An OSM way.
Definition: datatypes.h:206
double toDouble(bool *ok) const const
An OSM relation.
Definition: datatypes.h:270
A set of nodes, ways and relations.
Definition: datatypes.h:283
QXmlStreamAttributes attributes() const const
QVector< QStringRef > split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
Low-level types and functions to work with raw OSM data as efficiently as possible.
QStringRef name() const const
A member in a relation.
Definition: datatypes.h:241
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 25 2021 23:04:00 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.