Osmium  0.1
include/osmium/output/xml.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines