1 // Copyright 2008, Google Inc. All rights reserved. 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are met: 5 // 6 // 1. Redistributions of source code must retain the above copyright notice, 7 // this list of conditions and the following disclaimer. 8 // 2. Redistributions in binary form must reproduce the above copyright notice, 9 // this list of conditions and the following disclaimer in the documentation 10 // and/or other materials provided with the distribution. 11 // 3. Neither the name of Google Inc. nor the names of its contributors may be 12 // used to endorse or promote products derived from this software without 13 // specific prior written permission. 14 // 15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 // This file contains the declaration of the KmlFile class. 27 28 #ifndef KML_ENGINE_KML_FILE_H__ 29 #define KML_ENGINE_KML_FILE_H__ 30 31 #include <ostream> 32 #include <vector> 33 #include "boost/scoped_ptr.hpp" 34 #include "kml/base/attributes.h" 35 #include "kml/base/referent.h" 36 #include "kml/base/xml_namespaces.h" 37 #include "kml/base/util.h" 38 #include "kml/base/xml_file.h" 39 #include "kml/dom.h" 40 #include "kml/engine/engine_types.h" 41 #include "kml/engine/get_link_parents.h" 42 #include "kml/engine/object_id_parser_observer.h" 43 #include "kml/engine/shared_style_parser_observer.h" 44 45 namespace kmlengine { 46 47 class KmlCache; 48 49 // The KmlFile class represents the instance of a KML file from a given URL. 50 // A KmlFile manages an XML id domain and includes an internal map of all 51 // id'ed Objects, shared styles, and name'ed Schemas and a list of all links. 52 // KmlFile is a fundamental component of the KML Engine and is central in the 53 // use of shared style resolution. 54 class KmlFile : public kmlbase::XmlFile { 55 public: 56 // This creates a KmlFile from a memory buffer of either KML or KMZ data. 57 // In the case of KMZ the KmzFile module's ReadKml() is used to read the 58 // KML data from the KMZ archive. On any parse errors NULL is returned 59 // and a human readable error message is saved in the supplied string. 60 // The caller is responsible for deleting the KmlFile this creates. 61 static KmlFile* CreateFromParse(const string& kml_or_kmz_data, 62 string *errors); 63 64 // This method is for use with NetCache CacheItem. CreateFromString(const string & kml_or_kmz_data)65 static KmlFile* CreateFromString(const string& kml_or_kmz_data) { 66 // Internal KML fetch/parse (styleUrl, etc) errors are quietly ignored. 67 return CreateFromParse(kml_or_kmz_data, NULL); 68 } 69 70 // This method is for use with KmlCache. The purpose is to keep set_url() 71 // and set_kml_cache() private and at creation-time. 72 static KmlFile* CreateFromStringWithUrl(const string& kml_data, 73 const string& url, 74 KmlCache* kml_cache); 75 76 // This creates a KmlFile from the given element hierarchy. This variant of 77 // CreateFromImport fails on id duplicates. 78 static KmlFile* CreateFromImport(const kmldom::ElementPtr& element); 79 80 // This creates a KmlFile from the given element hierarchy. This variant of 81 // CreateFromImport employs a "last one wins" strategy for id duplicates. 82 static KmlFile* CreateFromImportLax(const kmldom::ElementPtr& element); 83 84 // This returns the root element of this KML file. get_root()85 const kmldom::ElementPtr get_root() const { 86 return kmldom::AsElement(XmlFile::get_root()); 87 } 88 89 // Deprecated. Use get_root(). root()90 const kmldom::ElementPtr root() const { 91 return get_root(); 92 } 93 94 // This serializes the KML from the root. The xmlns() value is added to 95 // the root element, the set of namespace prefixes to namespaces is added, 96 // and the encoding is set in a prepended XML header: 97 // <?xml version="1.0" encoding="ENCODING"> 98 // <kml xmlns="XMLNS" xmlns:PREFIX1="XMLNS1" xmlns:PREFIX2="XMLNS2"...> 99 // ... 100 // </kml> 101 bool SerializeToString(string* xml_output) const; 102 103 // This does as SerializeToString() except to an ostream. 104 bool SerializeToOstream(std::ostream* xml_output) const; 105 106 // This returns the XML header including the encoding: 107 // The default is this: "<?version="1.0" encoding="utf-8"?> 108 const string CreateXmlHeader() const; 109 110 // These methods access the XML encoding of the XML file. 111 // TODO: set should be create time only. set_encoding(const string & encoding)112 void set_encoding(const string& encoding) { 113 encoding_ = encoding; 114 } get_encoding()115 const string& get_encoding() const { 116 return encoding_; 117 } 118 119 // This returns the Object Element with the given id. A NULL Object is 120 // returned if no Object with this id exists in the KML file. 121 kmldom::ObjectPtr GetObjectById(const string& id) const; 122 123 // This returns the shared StyleSelector Element with the given id. NULL is 124 // returned if no StyleSelector with this id exists as a shared style 125 // selector in the KML file. 126 kmldom::StyleSelectorPtr GetSharedStyleById(const string& id) const; 127 get_shared_style_map()128 const SharedStyleMap& get_shared_style_map() const { 129 return shared_style_map_; 130 } 131 132 // This returns the all Elements that may have link children. See 133 // GetLinkParents() for more information. get_link_parent_vector()134 const ElementVector& get_link_parent_vector() const { 135 return link_parent_vector_; 136 } 137 138 // This is the KmlCache which created this KmlFile. This may be NULL if this 139 // KmlFile was not created using CreateFromStringWithUrl(). get_kml_cache()140 KmlCache* get_kml_cache() const { 141 return kml_cache_; 142 } 143 144 // Duplicate id attributes are illegal and should cause the parse to fail. 145 // However, Google Earth never enforced this in its KML ingest and thus the 146 // web has a lot of invalid KML. We attempt to parse this by default. A 147 // client may use set_strict_parse(true) to override this, which will 148 // instruct the ObjectIdParserObserver to fail on duplicate ids. set_strict_parse(bool val)149 void set_strict_parse(bool val) { 150 strict_parse_ = val; 151 } 152 153 private: 154 // Constructor is private. Use static Create methods. 155 KmlFile(); 156 157 // This is an internal helper function for the public CreateFromImport*() 158 // methods. 159 static KmlFile* CreateFromImportInternal(const kmldom::ElementPtr& element, 160 bool disallow_duplicate_ids); 161 162 // This is an internal method used in the static Create methods. 163 bool ParseFromString(const string& kml, string* errors); 164 165 // Only static Create methods can set the KmlCache. set_kml_cache(KmlCache * kml_cache)166 void set_kml_cache(KmlCache* kml_cache) { 167 kml_cache_ = kml_cache; 168 } 169 // These are helper functions for CreateFromParse(). 170 bool _CreateFromParse(const string& kml_or_kmz_data, 171 string* errors); 172 bool OpenAndParseKmz(const string& kmz_data, string* errors); 173 string encoding_; 174 // TODO: use XmlElement's id map. 175 ObjectIdMap object_id_map_; 176 SharedStyleMap shared_style_map_; 177 ElementVector link_parent_vector_; 178 KmlCache* kml_cache_; 179 bool strict_parse_; 180 LIBKML_DISALLOW_EVIL_CONSTRUCTORS(KmlFile); 181 }; 182 183 typedef boost::intrusive_ptr<KmlFile> KmlFilePtr; 184 185 } // end namespace kmlengine 186 187 #endif // KML_ENGINE_KML_FILE_H__ 188