Osmium
0.1
|
00001 #ifndef OSMIUM_OUTPUT_XML_HPP 00002 #define OSMIUM_OUTPUT_XML_HPP 00003 00004 /* 00005 00006 Copyright 2011 Jochen Topf <jochen@topf.org> and others (see README). 00007 00008 This file is part of Osmium (https://github.com/joto/osmium). 00009 00010 Osmium is free software: you can redistribute it and/or modify it under the 00011 terms of the GNU Lesser General Public License or (at your option) the GNU 00012 General Public License as published by the Free Software Foundation, either 00013 version 3 of the Licenses, or (at your option) any later version. 00014 00015 Osmium is distributed in the hope that it will be useful, but WITHOUT ANY 00016 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 00017 PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU 00018 General Public License for more details. 00019 00020 You should have received a copy of the Licenses along with Osmium. If not, see 00021 <http://www.gnu.org/licenses/>. 00022 00023 */ 00024 00025 // this is required to allow using libxml's xmlwriter in parallel to expat xml parser under debian 00026 #undef XMLCALL 00027 #include <libxml/xmlwriter.h> 00028 00029 // XXX error handling is mostly missing... 00030 00031 namespace Osmium { 00032 00033 namespace Output { 00034 00035 class XML : public Base { 00036 00037 public: 00038 00039 XML(Osmium::OSMFile& file) : Base(file), m_last_op('\0') { 00040 xml_writer = xmlNewTextWriter(xmlOutputBufferCreateFd(this->get_fd(), NULL)); 00041 } 00042 00043 ~XML() { 00044 } 00045 00046 void init(Osmium::OSM::Meta& meta) { 00047 xmlTextWriterSetIndent(xml_writer, 1); 00048 xmlTextWriterSetIndentString(xml_writer, BAD_CAST " "); 00049 xmlTextWriterStartDocument(xml_writer, NULL, "utf-8", NULL); // <?xml .. ?> 00050 00051 if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { 00052 xmlTextWriterStartElement(xml_writer, BAD_CAST "osmChange"); // <osmChange> 00053 } else { 00054 xmlTextWriterStartElement(xml_writer, BAD_CAST "osm"); // <osm> 00055 } 00056 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "version", BAD_CAST "0.6"); 00057 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "generator", BAD_CAST "Osmium (http://wiki.openstreetmap.org/wiki/Osmium)"); 00058 if (meta.bounds().defined()) { 00059 xmlTextWriterStartElement(xml_writer, BAD_CAST "bounds"); // <bounds> 00060 00061 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "minlon", "%.7f", meta.bounds().bl().lon()); 00062 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "minlat", "%.7f", meta.bounds().bl().lat()); 00063 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "maxlon", "%.7f", meta.bounds().tr().lon()); 00064 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "maxlat", "%.7f", meta.bounds().tr().lat()); 00065 00066 xmlTextWriterEndElement(xml_writer); // </bounds> 00067 } 00068 } 00069 00070 void node(const shared_ptr<Osmium::OSM::Node const>& node) { 00071 if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { 00072 open_close_op_tag(node->visible() ? (node->version() == 1 ? 'c' : 'm') : 'd'); 00073 } 00074 xmlTextWriterStartElement(xml_writer, BAD_CAST "node"); // <node> 00075 00076 write_meta(node); 00077 00078 const Osmium::OSM::Position position = node->position(); 00079 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "lat", "%.7f", position.lat()); 00080 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "lon", "%.7f", position.lon()); 00081 00082 write_tags(node->tags()); 00083 00084 xmlTextWriterEndElement(xml_writer); // </node> 00085 } 00086 00087 void way(const shared_ptr<Osmium::OSM::Way const>& way) { 00088 if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { 00089 open_close_op_tag(way->visible() ? (way->version() == 1 ? 'c' : 'm') : 'd'); 00090 } 00091 xmlTextWriterStartElement(xml_writer, BAD_CAST "way"); // <way> 00092 00093 write_meta(way); 00094 00095 Osmium::OSM::WayNodeList::const_iterator end = way->nodes().end(); 00096 for (Osmium::OSM::WayNodeList::const_iterator it = way->nodes().begin(); it != end; ++it) { 00097 xmlTextWriterStartElement(xml_writer, BAD_CAST "nd"); // <nd> 00098 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "ref", "%d", it->ref()); 00099 xmlTextWriterEndElement(xml_writer); // </nd> 00100 } 00101 00102 write_tags(way->tags()); 00103 00104 xmlTextWriterEndElement(xml_writer); // </way> 00105 } 00106 00107 void relation(const shared_ptr<Osmium::OSM::Relation const>& relation) { 00108 if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { 00109 open_close_op_tag(relation->visible() ? (relation->version() == 1 ? 'c' : 'm') : 'd'); 00110 } 00111 xmlTextWriterStartElement(xml_writer, BAD_CAST "relation"); // <relation> 00112 00113 write_meta(relation); 00114 00115 Osmium::OSM::RelationMemberList::const_iterator end = relation->members().end(); 00116 for (Osmium::OSM::RelationMemberList::const_iterator it = relation->members().begin(); it != end; ++it) { 00117 xmlTextWriterStartElement(xml_writer, BAD_CAST "member"); // <member> 00118 00119 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "type", BAD_CAST it->type_name()); 00120 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "ref", "%d", it->ref()); 00121 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "role", BAD_CAST it->role()); 00122 00123 xmlTextWriterEndElement(xml_writer); // </member> 00124 } 00125 00126 write_tags(relation->tags()); 00127 00128 xmlTextWriterEndElement(xml_writer); // </relation> 00129 } 00130 00131 void final() { 00132 if (m_file.get_type() == Osmium::OSMFile::FileType::Change()) { 00133 open_close_op_tag('\0'); 00134 } 00135 xmlTextWriterEndElement(xml_writer); // </osm> or </osmChange> 00136 xmlFreeTextWriter(xml_writer); 00137 m_file.close(); 00138 } 00139 00140 private: 00141 00142 xmlTextWriterPtr xml_writer; 00143 00144 void write_meta(const shared_ptr<Osmium::OSM::Object const>& object) { 00145 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "id", "%d", object->id()); 00146 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "version", "%d", object->version()); 00147 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "timestamp", BAD_CAST object->timestamp_as_string().c_str()); 00148 00149 // uid == 0 -> anonymous 00150 if (object->uid() > 0) { 00151 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "uid", "%d", object->uid()); 00152 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "user", BAD_CAST object->user()); 00153 } 00154 00155 xmlTextWriterWriteFormatAttribute(xml_writer, BAD_CAST "changeset", "%d", object->changeset()); 00156 00157 if (m_file.has_multiple_object_versions() && m_file.get_type() != Osmium::OSMFile::FileType::Change()) { 00158 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "visible", object->visible() ? BAD_CAST "true" : BAD_CAST "false"); 00159 } 00160 } 00161 00162 void write_tags(const Osmium::OSM::TagList& tags) { 00163 Osmium::OSM::TagList::const_iterator end = tags.end(); 00164 for (Osmium::OSM::TagList::const_iterator it = tags.begin(); it != end; ++it) { 00165 xmlTextWriterStartElement(xml_writer, BAD_CAST "tag"); // <tag> 00166 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "k", BAD_CAST it->key()); 00167 xmlTextWriterWriteAttribute(xml_writer, BAD_CAST "v", BAD_CAST it->value()); 00168 xmlTextWriterEndElement(xml_writer); // </tag> 00169 } 00170 } 00171 00172 char m_last_op; 00173 00174 void open_close_op_tag(char op) { 00175 if (op == m_last_op) { 00176 return; 00177 } 00178 00179 if (m_last_op) { 00180 xmlTextWriterEndElement(xml_writer); 00181 } 00182 00183 switch (op) { 00184 case 'c': 00185 xmlTextWriterStartElement(xml_writer, BAD_CAST "create"); 00186 break; 00187 case 'm': 00188 xmlTextWriterStartElement(xml_writer, BAD_CAST "modify"); 00189 break; 00190 case 'd': 00191 xmlTextWriterStartElement(xml_writer, BAD_CAST "delete"); 00192 break; 00193 } 00194 00195 m_last_op = op; 00196 } 00197 00198 }; // class XML 00199 00200 } // namespace Output 00201 00202 } // namespace Osmium 00203 00204 #endif // OSMIUM_OUTPUT_XML_HPP