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 implementation of the XsdHandler class.
27
28 #include "kml/xsd/xsd_handler.h"
29 #include <cstring> // strcmp
30 #include "boost/scoped_ptr.hpp"
31 #include "kml/base/attributes.h"
32 #include "kml/xsd/xsd_element.h"
33 #include "kml/xsd/xsd_file.h"
34 #include "kml/xsd/xsd_schema.h"
35 #include "kml/xsd/xsd_util.h"
36
37 using kmlbase::Attributes;
38
39 namespace kmlxsd {
40
41 // <xs:complexType name="..." abstract="...">
StartComplexType(const Attributes & attributes)42 void XsdHandler::StartComplexType(const Attributes& attributes) {
43 if (!current_type_) { // <xs:complexType> and/or <xs:simpleType>
44 current_type_ = XsdComplexType::Create(attributes);
45 }
46 }
47
48 // </xs:complexType">
49 // </xs:simpleType">
EndType()50 void XsdHandler::EndType() {
51 xsd_file_->add_type(current_type_);
52 current_type_ = NULL;
53 }
54
55 // <xs:extension base="...">
StartExtension(const Attributes & attributes)56 void XsdHandler::StartExtension(const Attributes& attributes) {
57 if (XsdComplexTypePtr complex_type =
58 XsdComplexType::AsComplexType(current_type_)) {
59 string base;
60 if (attributes.GetString(kBase, &base)) {
61 complex_type->set_extension_base(base);
62 }
63 }
64 }
65
66 // <xs:simpleType name="..."/>
StartSimpleType(const Attributes & attributes)67 void XsdHandler::StartSimpleType(const Attributes& attributes) {
68 if (!current_type_) { // <xs:simpleType is never nested...
69 current_type_ = XsdSimpleType::Create(attributes);
70 }
71 }
72
73 // <xs:restriction base="...">
StartRestriction(const Attributes & attributes)74 void XsdHandler::StartRestriction(const Attributes& attributes) {
75 if (XsdSimpleTypePtr simple_type =
76 XsdSimpleType::AsSimpleType(current_type_)) {
77 string base;
78 if (attributes.GetString(kBase, &base)) {
79 simple_type->set_restriction_base(base);
80 }
81 }
82 }
83
84 // <xs:enumeration value="...">
StartEnumeration(const Attributes & attributes)85 void XsdHandler::StartEnumeration(const Attributes& attributes) {
86 if (XsdSimpleTypePtr simple_type =
87 XsdSimpleType::AsSimpleType(current_type_)) {
88 string value;
89 if (attributes.GetString(kValue, &value)) {
90 simple_type->add_enumeration(value);
91 }
92 }
93 }
94
95 // <xs:element name="..." type="..." default=".."/>
96 // <xs:element ref="..." minOccurs="..." maxOccurs="..."/>
StartXsElement(const Attributes & attributes)97 void XsdHandler::StartXsElement(const Attributes& attributes) {
98 XsdElement* element = XsdElement::Create(attributes);
99 if (!element) {
100 return;
101 }
102
103 // Is this a global element?
104 if (parse_.top() == kSchema) {
105 xsd_file_->add_element(element);
106 } else if (XsdComplexTypePtr complex_type =
107 XsdComplexType::AsComplexType(current_type_)) {
108 // Is it a child of <xs:complexType>?
109 complex_type->add_element(element);
110 }
111 }
112
113 // ExpatHandler::StartElement
StartElement(const string & xs_element_name,const kmlbase::StringVector & atts)114 void XsdHandler::StartElement(const string& xs_element_name,
115 const kmlbase::StringVector& atts) {
116 boost::scoped_ptr<Attributes> attributes(Attributes::Create(atts));
117
118 if (xs_element_name.compare(kSchema) == 0) {
119 xsd_file_->set_schema(XsdSchema::Create(*attributes));
120 } else if (xs_element_name.compare(kElement) == 0) {
121 StartXsElement(*attributes);
122 } else if (xs_element_name.compare(kComplexType) == 0) {
123 StartComplexType(*attributes);
124 } else if (xs_element_name.compare(kExtension) == 0) {
125 StartExtension(*attributes);
126 } else if (xs_element_name.compare(kSimpleType) == 0) {
127 StartSimpleType(*attributes);
128 } else if (xs_element_name.compare(kRestriction) == 0) {
129 StartRestriction(*attributes);
130 } else if (xs_element_name.compare(kEnumeration) == 0) {
131 StartEnumeration(*attributes);
132 }
133
134 // Always push, and we always pop in EndElement().
135 parse_.push(xs_element_name);
136 }
137
138 // ExpatHandler::EndElement
EndElement(const string & xs_element_name)139 void XsdHandler::EndElement(const string& xs_element_name) {
140 // Always pop, because we always push in StartElement().
141 parse_.pop();
142 if (xs_element_name.compare(kComplexType) == 0) {
143 EndType();
144 } else if (xs_element_name.compare(kSimpleType) == 0) {
145 EndType();
146 }
147 }
148
149 } // end namespace kmlxsd
150