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 maps the C-based expat to a general purpose C++ ExpatHandler class.
27 // KmlHandler is the only such handler at present, hence the static nature
28 // of the ExpatParser() function.
29
30 #include "kml/dom/kml_funcs.h"
31 #include <cstring>
32 #include <sstream>
33 #include "kml/base/attributes.h"
34 #include "kml/base/expat_parser.h"
35 #include "kml/base/expat_handler_ns.h"
36 #include "kml/base/xmlns.h"
37 #include "kml/dom/element.h"
38 #include "kml/dom/kml_handler.h"
39 #include "kml/dom/kml_handler_ns.h"
40 #include "kml/dom/parser.h"
41 #include "kml/dom/parser_observer.h"
42
43 namespace kmldom {
44
45 // This is an internal API to add Element-level SAX-style handlers to
46 // a given parser instance. TODO: determine how/if to make public and SWIG.
AddObserver(ParserObserver * parser_observer)47 void Parser::AddObserver(ParserObserver* parser_observer) {
48 observers_.push_back(parser_observer);
49 }
50
51 // This is the internal API to the parser. TODO: determine how/if to make
52 // public and SWIG.
Parse(const string & kml,string * errors)53 ElementPtr Parser::Parse(const string& kml, string* errors) {
54 KmlHandler kml_handler(observers_);
55 kmlbase::ExpatParser parser(&kml_handler, false);
56 if (kmlbase::ExpatParser::ParseString(kml, &kml_handler, errors, false)) {
57 return kml_handler.PopRoot();
58 }
59 return NULL;
60 }
61
62
63 // As Parser::Parse(), but invokes the underlying XML parser's namespace-aware
64 // mode.
ParseNS(const string & kml,string * errors)65 ElementPtr Parser::ParseNS(const string& kml, string* errors) {
66 KmlHandlerNS kml_handler(observers_);
67 if (kmlbase::ExpatParser::ParseString(kml, &kml_handler, errors, true)) {
68 return kml_handler.PopRoot();
69 }
70 return NULL;
71 }
72
73 // This is obviously a bit of a special case. If libkml always used full
74 // namespace-aware parsing we'd not need this.
ParseAtom(const string & atom,string * errors)75 ElementPtr Parser::ParseAtom(const string& atom, string* errors) {
76 // Create a garden variety KML parser with "short-hand" namespace prefixes
77 // for Atom.
78 KmlHandler kml_handler(observers_);
79 kmlbase::Attributes attributes;
80 // Create a namespace aware expat handler which converts the Atom namespace
81 // elements to the "short-hand" namespace prefixing used in KmlHandler.
82 // Here's the overall flow:
83 // 1) instance file has <feed xmlns="http://www.w3.org/2005/Atom">...
84 // 2) namespace-enabled expat turns this into:
85 // <http://www.w3.org/2005/Atom|feed>
86 // 3) ExpatHandlerNns turns this to <atom:feed>
87 // 4) KmlHandler knows that <atom:feed> is kmldom::AtomFeed
88 attributes.SetValue("xmlns", "http://www.opengis.net/kml/2.2");
89 attributes.SetValue("xmlns:atom", "http://www.w3.org/2005/Atom");
90 boost::scoped_ptr<kmlbase::Xmlns> xmlns(kmlbase::Xmlns::Create(attributes));
91 kmlbase::ExpatHandlerNs expat_handler_ns(&kml_handler, xmlns.get());
92 if (kmlbase::ExpatParser::ParseString(atom, &expat_handler_ns, errors,
93 true)) {
94 return kml_handler.PopRoot();
95 }
96 return NULL;
97 }
98
99 // This is the implementation of the public API to parse KML from a memory
100 // buffer.
Parse(const string & kml,string * errors)101 ElementPtr Parse(const string& kml, string* errors) {
102 Parser parser;
103 return parser.Parse(kml, errors);
104 }
105
106 // As Parse(), but invokes the underlying XML parser's namespace-aware mode.
ParseNS(const string & kml,string * errors)107 ElementPtr ParseNS(const string& kml, string* errors) {
108 Parser parser;
109 return parser.ParseNS(kml, errors);
110 }
111
112 // Parse the KML in the given string. NULL is returned on any parse errors,
113 // but the error string is unavailable with this function.
ParseKml(const string & kml)114 ElementPtr ParseKml(const string& kml) {
115 return Parse(kml, NULL);
116 }
117
ParseAtom(const string & atom,string * errors)118 ElementPtr ParseAtom(const string& atom, string* errors) {
119 Parser parser;
120 return parser.ParseAtom(atom, errors);
121 }
122
123 } // end namespace kmldom
124