1 : /******************************************************************************
2 : * $Id: parsexsd.cpp 17629 2009-09-10 14:51:45Z chaitanya $
3 : *
4 : * Project: GML Reader
5 : * Purpose: Implementation of GMLReader::ParseXSD() method.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2005, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gmlreader.h"
31 : #include "cpl_error.h"
32 :
33 : #if HAVE_XERCES != 0 || defined(HAVE_EXPAT)
34 :
35 : #include "gmlreaderp.h"
36 : #include "cpl_conv.h"
37 :
38 : /************************************************************************/
39 : /* StripNS() */
40 : /* */
41 : /* Return potentially shortened form of string with namespace */
42 : /* stripped off if there is one. Returns pointer into */
43 : /* original string. */
44 : /************************************************************************/
45 :
46 15 : const char *StripNS( const char *pszFullValue )
47 :
48 : {
49 15 : const char *pszColon = strstr( pszFullValue, ":" );
50 15 : if( pszColon == NULL )
51 0 : return pszFullValue;
52 : else
53 15 : return pszColon + 1;
54 : }
55 :
56 : /************************************************************************/
57 : /* ParseXSD() */
58 : /************************************************************************/
59 :
60 3 : int GMLReader::ParseXSD( const char *pszFile )
61 :
62 : {
63 3 : if( pszFile == NULL )
64 0 : return FALSE;
65 :
66 : /* -------------------------------------------------------------------- */
67 : /* Load the raw XML file. */
68 : /* -------------------------------------------------------------------- */
69 3 : CPLXMLNode *psXSDTree = CPLParseXMLFile( pszFile );
70 :
71 3 : if( psXSDTree == NULL )
72 0 : return FALSE;
73 :
74 : /* -------------------------------------------------------------------- */
75 : /* Strip off any namespace qualifiers. */
76 : /* -------------------------------------------------------------------- */
77 3 : CPLStripXMLNamespace( psXSDTree, NULL, TRUE );
78 :
79 : /* -------------------------------------------------------------------- */
80 : /* Find <schema> root element. */
81 : /* -------------------------------------------------------------------- */
82 3 : CPLXMLNode *psSchemaNode = CPLGetXMLNode( psXSDTree, "=schema" );
83 3 : if( psSchemaNode == NULL )
84 : {
85 0 : CPLDestroyXMLNode( psXSDTree );
86 0 : return FALSE;
87 : }
88 :
89 : /* ==================================================================== */
90 : /* Process each feature class definition. */
91 : /* ==================================================================== */
92 : CPLXMLNode *psThis;
93 3 : int bIsLevel0 = TRUE;
94 :
95 33 : for( psThis = psSchemaNode->psChild;
96 : psThis != NULL; psThis = psThis->psNext )
97 : {
98 : /* -------------------------------------------------------------------- */
99 : /* Check for <xs:element> node. */
100 : /* -------------------------------------------------------------------- */
101 30 : if( psThis->eType != CXT_Element
102 : || !EQUAL(psThis->pszValue,"element") )
103 24 : continue;
104 :
105 : /* -------------------------------------------------------------------- */
106 : /* Check the substitution group. */
107 : /* -------------------------------------------------------------------- */
108 : const char *pszSubGroup =
109 6 : StripNS(CPLGetXMLValue(psThis,"substitutionGroup",""));
110 :
111 : // Old OGR produced elements for the feature collection.
112 6 : if( EQUAL(pszSubGroup, "_FeatureCollection") )
113 3 : continue;
114 :
115 3 : if( !EQUAL(pszSubGroup, "_Feature") )
116 : {
117 0 : bIsLevel0 = FALSE;
118 0 : break;
119 : }
120 :
121 : /* -------------------------------------------------------------------- */
122 : /* Get name */
123 : /* -------------------------------------------------------------------- */
124 : const char *pszName;
125 :
126 3 : pszName = CPLGetXMLValue( psThis, "name", NULL );
127 3 : if( pszName == NULL )
128 : {
129 0 : bIsLevel0 = FALSE;
130 0 : break;
131 : }
132 :
133 : /* -------------------------------------------------------------------- */
134 : /* Get type and verify relationship with name. */
135 : /* -------------------------------------------------------------------- */
136 : const char *pszType;
137 :
138 3 : pszType = CPLGetXMLValue( psThis, "type", NULL );
139 3 : if( strstr( pszType, ":" ) != NULL )
140 3 : pszType = strstr( pszType, ":" ) + 1;
141 3 : if( pszType == NULL || !EQUALN(pszType,pszName,strlen(pszName))
142 : || !(EQUAL(pszType+strlen(pszName),"_Type") ||
143 : EQUAL(pszType+strlen(pszName),"Type")) )
144 : {
145 0 : bIsLevel0 = FALSE;
146 0 : break;
147 : }
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* The very next element should be the corresponding */
151 : /* complexType declaration for the element. */
152 : /* -------------------------------------------------------------------- */
153 3 : psThis = psThis->psNext;
154 6 : while( psThis != NULL && psThis->eType == CXT_Comment )
155 0 : psThis = psThis->psNext;
156 :
157 3 : if( psThis == NULL
158 : || psThis->eType != CXT_Element
159 : || !EQUAL(psThis->pszValue,"complexType")
160 : || !EQUAL(CPLGetXMLValue(psThis,"name",""),pszType) )
161 : {
162 0 : bIsLevel0 = FALSE;
163 0 : break;
164 : }
165 :
166 : /* -------------------------------------------------------------------- */
167 : /* Grab the sequence of extensions greatgrandchild. */
168 : /* -------------------------------------------------------------------- */
169 : CPLXMLNode *psAttrSeq =
170 : CPLGetXMLNode( psThis,
171 3 : "complexContent.extension.sequence" );
172 :
173 3 : if( psAttrSeq == NULL )
174 : {
175 0 : bIsLevel0 = FALSE;
176 0 : break;
177 : }
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* We are pretty sure this going to be a valid Feature class */
181 : /* now, so create it. */
182 : /* -------------------------------------------------------------------- */
183 3 : GMLFeatureClass *poClass = new GMLFeatureClass( pszName );
184 :
185 : /* -------------------------------------------------------------------- */
186 : /* Loop over each of the attribute elements being defined for */
187 : /* this feature class. */
188 : /* -------------------------------------------------------------------- */
189 : CPLXMLNode *psAttrDef;
190 :
191 15 : for( psAttrDef = psAttrSeq->psChild;
192 : psAttrDef != NULL;
193 : psAttrDef = psAttrDef->psNext )
194 : {
195 12 : if( !EQUAL(psAttrDef->pszValue,"element") )
196 0 : continue;
197 :
198 : // For now we skip geometries .. fixup later.
199 12 : if( CPLGetXMLNode( psAttrDef, "simpleType" ) == NULL )
200 3 : continue;
201 :
202 : GMLPropertyDefn *poProp = new GMLPropertyDefn(
203 : CPLGetXMLValue( psAttrDef, "name", "unnamed" ),
204 9 : CPLGetXMLValue( psAttrDef, "name", "unnamed" ) );
205 :
206 : const char *pszBase =
207 : StripNS( CPLGetXMLValue( psAttrDef,
208 9 : "simpleType.restriction.base", "" ));
209 :
210 9 : if( EQUAL(pszBase,"decimal") )
211 : {
212 3 : poProp->SetType( GMLPT_Real );
213 : const char *pszWidth =
214 : CPLGetXMLValue( psAttrDef,
215 3 : "simpleType.restriction.totalDigits.value", "0" );
216 : const char *pszPrecision =
217 : CPLGetXMLValue( psAttrDef,
218 3 : "simpleType.restriction.fractionDigits.value", "0" );
219 3 : poProp->SetWidth( atoi(pszWidth) );
220 3 : poProp->SetPrecision( atoi(pszPrecision) );
221 : }
222 :
223 6 : else if( EQUAL(pszBase,"float")
224 : || EQUAL(pszBase,"double") )
225 0 : poProp->SetType( GMLPT_Real );
226 :
227 6 : else if( EQUAL(pszBase,"integer") )
228 : {
229 2 : poProp->SetType( GMLPT_Integer );
230 : const char *pszWidth =
231 : CPLGetXMLValue( psAttrDef,
232 2 : "simpleType.restriction.totalDigits.value", "0" );
233 2 : poProp->SetWidth( atoi(pszWidth) );
234 : }
235 :
236 4 : else if( EQUAL(pszBase,"string") )
237 : {
238 4 : poProp->SetType( GMLPT_String );
239 : const char *pszWidth =
240 : CPLGetXMLValue( psAttrDef,
241 4 : "simpleType.restriction.maxLength.value", "0" );
242 4 : poProp->SetWidth( atoi(pszWidth) );
243 : }
244 :
245 : else
246 0 : poProp->SetType( GMLPT_Untyped );
247 :
248 9 : poClass->AddProperty( poProp );
249 : }
250 :
251 : /* -------------------------------------------------------------------- */
252 : /* Class complete, add to reader class list. */
253 : /* -------------------------------------------------------------------- */
254 3 : poClass->SetSchemaLocked( TRUE );
255 :
256 3 : AddClass( poClass );
257 : }
258 :
259 3 : CPLDestroyXMLNode( psXSDTree );
260 :
261 3 : if( m_nClassCount > 0 )
262 : {
263 3 : SetClassListLocked( TRUE );
264 3 : return TRUE;
265 : }
266 : else
267 0 : return FALSE;
268 : }
269 :
270 : #endif /* HAVE_XERCES == 1 || defined(HAVE_EXPAT) */
271 :
|