wms/client/XMLParser.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 #include "XMLParser.h"
21 
22 #include <iostream>
23 
24 //BOOST
25 #include <boost/algorithm/string.hpp>
26 
27 #include "../../../../common/StringUtils.h"
28 #include "../../../core/Utils.h"
29 #include "../../../core/Exception.h"
30 
32  m_version("1.3.0")
33 {
34 }
35 
37 
39 {
40  // Read XML file
41  std::unique_ptr<te::xml::Reader> reader(te::xml::ReaderFactory::make("XERCES"));
42  reader->setValidationScheme(false);
43  reader->setDoSchema(false);
44  reader->setIgnoreWhiteSpaces(true);
45  reader->setCacheGrammarFromParse(false);
46  reader->setUseCachedGrammarInParse(false);
47 
48  reader->read(xmlPath);
49 
50  // Validate the XML file
51  if(!reader->next())
52  {
53  throw te::ws::core::Exception() << te::ErrorDescription(TE_TR("Could not read the WMS 1.3.0 GetCapabilities response XML file!"));
54  }
55 
56  if(!boost::iequals(reader->getElementLocalName(), "WMS_Capabilities"))
57  {
58  throw te::ws::core::WrongVersionException() << te::ErrorDescription(TE_TR("Could not find a WMS 1.3.0 GetCapabilities response in the received XML!"));
59  }
60 
62 
63  while (reader->next())
64  {
65  if(boost::iequals(reader->getElementLocalName(), "Capability"))
66  {
67  capabilities.m_capability = this->parseCapability(reader);
68  }
69  }
70 
71  return capabilities;
72 }
73 
74 te::ws::ogc::wms::Capability te::ws::ogc::wms::XMLParser::parseCapability(const std::unique_ptr<te::xml::Reader> &reader)
75 {
76  Capability capability;
77 
78  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "Capability")))
79  {
80  if(boost::iequals(reader->getElementLocalName(), "Request"))
81  {
82  capability.m_request = this->parseRequest(reader);
83  }
84  else if (boost::iequals(reader->getElementLocalName(), "Layer"))
85  {
86  capability.m_layer = this->parseLayers(reader);
87  }
88  }
89 
90  return capability;
91 }
92 
93 te::ws::ogc::wms::Request te::ws::ogc::wms::XMLParser::parseRequest(const std::unique_ptr<te::xml::Reader> &reader)
94 {
96 
97  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "Request")))
98  {
99 
100  if(boost::iequals(reader->getElementLocalName(), "GetCapabilities"))
101  {
102  request.m_getCapabilities = this->parseOperation(reader, "GetCapabilities");
103  }
104  else if(boost::iequals(reader->getElementLocalName(), "GetMap"))
105  {
106  request.m_getMap = this->parseOperation(reader, "GetMap");
107  }
108  else if(boost::iequals(reader->getElementLocalName(), "GetFeatureInfo"))
109  {
110  request.m_getFeatureInfo = this->parseOperation(reader, "GetFeatureInfo");
111  }
112  }
113 
114  return request;
115 }
116 
117 te::ws::ogc::wms::Layer te::ws::ogc::wms::XMLParser::parseLayers(const std::unique_ptr<te::xml::Reader>& reader)
118 {
119  Layer layer;
120 
121  if (reader->hasAttrs())
122  {
123  for (size_t i = 0; i < reader->getNumberOfAttrs(); i++)
124  {
125  if(boost::iequals(reader->getAttrLocalName(i), "queryable"))
126  layer.m_queryable = (reader->getAttrAsInt32("queryable") != 0) ? true : false;
127  else if (boost::iequals(reader->getAttrLocalName(i), "cascaded"))
128  layer.m_cascaded = (reader->getAttrAsInt32("cascaded") != 0) ? true : false;
129  else if (boost::iequals(reader->getAttrLocalName(i), "opaque"))
130  layer.m_opaque = (reader->getAttrAsInt32("opaque") != 0) ? true : false;
131  else if (boost::iequals(reader->getAttrLocalName(i), "noSubsets"))
132  layer.m_noSubsets = (reader->getAttrAsInt32("noSubsets") != 0) ? true : false;
133  else if (boost::iequals(reader->getAttrLocalName(i), "fixedWidth"))
134  layer.m_fixedWidth = (reader->getAttrAsInt32("fixedWidth") != 0) ? true : false;
135  else if (boost::iequals(reader->getAttrLocalName(i), "fixedHeight"))
136  layer.m_fixedHeight = (reader->getAttrAsInt32("fixedHeight") != 0) ? true : false;
137  }
138  }
139 
140  std::vector<std::string> crsList;
141  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "Layer")))
142  {
143  if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Name"))
144  {
145  layer.m_name = reader->getElementValue();
146  }
147  else if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Title"))
148  {
149  layer.m_title = reader->getElementValue();
150  }
151  else if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Abstract"))
152  {
153  layer.m_abstract = reader->getElementValue();
154  }
155  else if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "CRS"))
156  {
157  crsList.push_back(reader->getElementValue());
158  }
159  else if(reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "KeywordList"))
160  {
161  std::vector<std::string> keywordList;
162 
163  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "KeywordList")))
164  {
165  if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Keyword"))
166  {
167  keywordList.push_back(reader->getElementValue());
168  }
169  }
170 
171  layer.m_keywordList = keywordList;
172  }
173  else if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "EX_GeographicBoundingBox"))
174  {
175  layer.m_geoBoundingBox = this->parseGeographicBoundingBox(reader);
176  }
177  else if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "BoundingBox") && reader->hasAttrs())
178  {
179  layer.m_boundingBoxes.push_back(this->parseBoundingBox(reader));
180  }
181  else if (boost::iequals(reader->getElementLocalName(), "Dimension") && reader->hasAttrs())
182  {
183  layer.m_dimensions.push_back(this->parseDimension(reader));
184  }
185  else if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "Style"))
186  {
187  layer.m_styles.push_back(this->parseStyle(reader));
188  }
189  else if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "MinScaleDenominator"))
190  {
191  layer.m_minScaleDenominator = reader->getElementValueAsDouble();
192  }
193  else if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "MaxScaleDenominator"))
194  {
195  layer.m_maxScaleDenominator = reader->getElementValueAsDouble();
196  }
197  else if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "Layer"))
198  {
199  Layer subLayer = this->parseLayers(reader);
200  layer.m_layers.push_back(subLayer);
201  }
202  }
203 
204  layer.m_crs = crsList;
205 
206  return layer;
207 }
208 
210 {
211  GeographicBoundingBox geoBoundingBox;
212 
213  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "EX_GeographicBoundingBox")))
214  {
215  if(reader->getNodeType() == te::xml::VALUE)
216  {
217  if(boost::iequals(reader->getElementLocalName(), "westBoundLongitude"))
218  geoBoundingBox.m_westBoundLongitude = reader->getElementValueAsDouble();
219  else if(boost::iequals(reader->getElementLocalName(), "eastBoundLongitude"))
220  geoBoundingBox.m_eastBoundLongitude = reader->getElementValueAsDouble();
221  else if(boost::iequals(reader->getElementLocalName(), "southBoundLatitude"))
222  geoBoundingBox.m_southBoundLatitude = reader->getElementValueAsDouble();
223  else if(boost::iequals(reader->getElementLocalName(), "northBoundLatitude"))
224  geoBoundingBox.m_northBoundLatitude = reader->getElementValueAsDouble();
225  }
226  }
227 
228  return geoBoundingBox;
229 }
230 
232 {
233  BoundingBox box;
234 
235  box.m_crs = reader->getAttr("CRS");
236 
237  bool isInverted = te::ws::core::IsInvertedEPSG(box.m_crs);
238 
239  if(isInverted)
240  {
241  box.m_minX = reader->getAttrAsDouble("miny");
242  box.m_minY = reader->getAttrAsDouble("minx");
243  box.m_maxX = reader->getAttrAsDouble("maxy");
244  box.m_maxY = reader->getAttrAsDouble("maxx");
245  }
246  else
247  {
248  box.m_minX = reader->getAttrAsDouble("minx");
249  box.m_minY = reader->getAttrAsDouble("miny");
250  box.m_maxX = reader->getAttrAsDouble("maxx");
251  box.m_maxY = reader->getAttrAsDouble("maxy");
252  }
253 
254  return box;
255 }
256 
257 te::ws::ogc::wms::Dimension te::ws::ogc::wms::XMLParser::parseDimension(const std::unique_ptr<te::xml::Reader> &reader)
258 {
259  Dimension dimension;
260 
261  for (unsigned int i = 0; i < reader->getNumberOfAttrs(); i++)
262  {
263  if(boost::iequals(reader->getAttrLocalName(i), "name"))
264  dimension.m_name = reader->getAttr("name");
265  else if (boost::iequals(reader->getAttrLocalName(i), "units"))
266  dimension.m_units = reader->getAttr("units");
267  else if (boost::iequals(reader->getAttrLocalName(i), "unitSymbol"))
268  dimension.m_unitSymbol = reader->getAttr("unitSymbol");
269  else if (boost::iequals(reader->getAttrLocalName(i), "default"))
270  dimension.m_default = reader->getAttr("default");
271  else if (boost::iequals(reader->getAttrLocalName(i), "multipleValues"))
272  dimension.m_multipleValues = (reader->getAttrAsInt32("multipleValues") != 0) ? true : false;
273  else if (boost::iequals(reader->getAttrLocalName(i), "nearestValue"))
274  dimension.m_nearestValue = (reader->getAttrAsInt32("nearestValue") != 0) ? true : false;
275  else if (boost::iequals(reader->getAttrLocalName(i), "current"))
276  dimension.m_current = (reader->getAttrAsInt32("current") != 0) ? true : false;
277  }
278 
279  if(boost::iequals(dimension.m_name, "time"))
280  {
281  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "Dimension")))
282  {
283  if(reader->getNodeType() == te::xml::VALUE)
284  {
285  std::string allowedValuesStr = reader->getElementValue();
286 
287  std::vector<std::string> allowedValues = te::common::SplitString(allowedValuesStr, ',');
288 
289  dimension.m_allowedValues = allowedValues;
290  }
291  }
292  }
293 
294  return dimension;
295 }
296 
297 te::ws::ogc::wms::Style te::ws::ogc::wms::XMLParser::parseStyle(const std::unique_ptr<te::xml::Reader> &reader)
298 {
299  Style style;
300 
301  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "Style")))
302  {
303  if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Name"))
304  {
305  style.m_name = reader->getElementValue();
306  }
307  else if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Title"))
308  {
309  style.m_title = reader->getElementValue();
310  }
311  else if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Abstract"))
312  {
313  style.m_abstract = reader->getElementValue();
314  }
315  else if(reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "LegendURL"))
316  {
317  style.m_legendURL = this->parseLegendURL(reader);
318  }
319  else if(reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "StyleSheetURL"))
320  {
321  style.m_styleSheetURL = this->parseStyleSheetURL(reader);
322  }
323  else if(reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "StyleURL"))
324  {
325  style.m_styleURL = this->parseStyleURL(reader);
326  }
327  }
328 
329  return style;
330 }
331 
332 te::ws::ogc::wms::LegendURL te::ws::ogc::wms::XMLParser::parseLegendURL(const std::unique_ptr<te::xml::Reader> &reader)
333 {
334  LegendURL legendURL;
335 
336  if (reader->hasAttrs())
337  {
338  for (unsigned int i = 0; i < reader->getNumberOfAttrs(); i++)
339  {
340  if (boost::iequals(reader->getAttrLocalName(i), "width"))
341  legendURL.m_width = reader->getAttrAsInt32("width");
342  else if (boost::iequals(reader->getAttrLocalName(i), "height"))
343  legendURL.m_height = reader->getAttrAsInt32("height");
344  }
345  }
346 
347  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "LegendURL")))
348  {
349  if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Format"))
350  {
351  legendURL.m_format = reader->getElementValue();
352  }
353  else if(boost::iequals(reader->getElementLocalName(), "OnlineResource") && reader->hasAttrs())
354  {
355  legendURL.m_onlineResource = this->parseOnlineResource(reader);
356  }
357  }
358 
359  return legendURL;
360 }
361 
363 {
364  OnlineResource onlineResource;
365 
366  for (unsigned int i = 0; i < reader->getNumberOfAttrs(); i++)
367  {
368  if(boost::iequals(reader->getAttrLocalName(i), "href"))
369  onlineResource.m_href = reader->getAttr(i);
370  else if (boost::iequals(reader->getAttrLocalName(i), "type"))
371  onlineResource.m_type = reader->getAttr(i);
372  }
373 
374  return onlineResource;
375 }
376 
378 {
379  StyleSheetURL styleSheet;
380 
381  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "StyleSheetURL")))
382  {
383  if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Format"))
384  {
385  styleSheet.m_format = reader->getElementValue();
386  }
387  else if(boost::iequals(reader->getElementLocalName(), "OnlineResource") && reader->hasAttrs())
388  {
389  styleSheet.m_onlineResource = this->parseOnlineResource(reader);
390  }
391  }
392 
393  return styleSheet;
394 }
395 
396 te::ws::ogc::wms::StyleURL te::ws::ogc::wms::XMLParser::parseStyleURL(const std::unique_ptr<te::xml::Reader> &reader)
397 {
398  StyleURL style;
399 
400  while (reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "StyleURL")))
401  {
402  if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Format"))
403  {
404  style.m_format = reader->getElementValue();
405  }
406  else if(boost::iequals(reader->getElementLocalName(), "OnlineResource") && reader->hasAttrs())
407  {
408  style.m_onlineResource = this->parseOnlineResource(reader);
409  }
410  }
411 
412  return style;
413 }
414 
415 te::ws::ogc::wms::Operation te::ws::ogc::wms::XMLParser::parseOperation(const std::unique_ptr<te::xml::Reader> &reader, const std::string& operationName)
416 {
417  Operation operation;
418 
419  while(reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), operationName)))
420  {
421  if(reader->getNodeType() == te::xml::VALUE && boost::iequals(reader->getElementLocalName(), "Format"))
422  {
423  operation.m_formats.push_back(reader->getElementValue());
424  }
425  else if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "DCPType"))
426  {
427  while(reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "DCPType")))
428  {
429  if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "HTTP"))
430  {
431  operation.m_dcps.push_back(this->parseHTTP(reader));
432  }
433  }
434  }
435  }
436 
437  return operation;
438 }
439 
440 te::ws::ogc::wms::HTTP te::ws::ogc::wms::XMLParser::parseHTTP(const std::unique_ptr<te::xml::Reader> &reader)
441 {
442  HTTP http;
443 
444  while(reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "HTTP")))
445  {
446  if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "Get"))
447  {
448  while(reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "Get")))
449  {
450  if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "OnlineResource"))
451  {
452  http.m_get = this->parseOnlineResource(reader);
453  }
454  }
455  }
456  else if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "Post"))
457  {
458  while(reader->next() && !(reader->getNodeType() == te::xml::END_ELEMENT && boost::iequals(reader->getElementLocalName(), "Post")))
459  {
460  if (reader->getNodeType() == te::xml::START_ELEMENT && boost::iequals(reader->getElementLocalName(), "OnlineResource"))
461  {
462  http.m_post = this->parseOnlineResource(reader);
463  }
464  }
465  }
466  }
467 
468  return http;
469 }
virtual Request parseRequest(const std::unique_ptr< te::xml::Reader > &reader)
virtual BoundingBox parseBoundingBox(const std::unique_ptr< te::xml::Reader > &reader)
TECOMMONEXPORT std::vector< std::string > SplitString(const std::string &str, const char &delimiter)
Definition: StringUtils.cpp:32
virtual Style parseStyle(const std::unique_ptr< te::xml::Reader > &reader)
The Capability WMS 1.3.0 struct.
std::vector< std::string > m_crs
virtual HTTP parseHTTP(const std::unique_ptr< te::xml::Reader > &reader)
TEWSCOREEXPORT bool IsInvertedEPSG(const std::string &epsg)
This function gets true for EPSGs that has inverted axis-order. Otherwise false. This implementation ...
static te::xml::Reader * make()
It creates a new XML reader using the dafault implementation.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
boost::error_info< struct tag_error_description, std::string > ErrorDescription
The base type for error report messages.
virtual GeographicBoundingBox parseGeographicBoundingBox(const std::unique_ptr< te::xml::Reader > &reader)
The Capability WMS 1.3.0 struct.
std::vector< std::string > m_formats
virtual Layer parseLayers(const std::unique_ptr< te::xml::Reader > &reader)
virtual OnlineResource parseOnlineResource(const std::unique_ptr< te::xml::Reader > &reader)
std::vector< Dimension > m_dimensions
te::da::DataSourceCapabilities capabilities
std::vector< std::string > m_allowedValues
virtual StyleSheetURL parseStyleSheetURL(const std::unique_ptr< te::xml::Reader > &reader)
The Dimension WMS 1.3.0 struct.
The Operation WMS 1.3.0 struct.
virtual WMSCapabilities parseCapabilities(const std::string &xmlPath)
Method responsible to parse a WMS XML GetCapabilities file and create an WMSCapabilities instance wit...
The Layer WMS 1.3.0 struct.
virtual LegendURL parseLegendURL(const std::unique_ptr< te::xml::Reader > &reader)
virtual StyleURL parseStyleURL(const std::unique_ptr< te::xml::Reader > &reader)
The OnlineResource WMS 1.3.0 struct.
Base exception class for WS Core Runtime Library.
The LegendURL WMS 1.3.0 struct.
The Style WMS 1.3.0 struct.
virtual Dimension parseDimension(const std::unique_ptr< te::xml::Reader > &reader)
The Request WMS 1.3.0 struct.
std::vector< std::string > m_keywordList
The StyleSheeetURL WMS 1.3.0 struct.
virtual Capability parseCapability(const std::unique_ptr< te::xml::Reader > &reader)
virtual Operation parseOperation(const std::unique_ptr< te::xml::Reader > &reader, const std::string &operationName)
Exception to be used when a XML has an unsupported version by XMLParser.
GeographicBoundingBox m_geoBoundingBox
The GeographicBoundingBox WMS 1.3.0 struct.
The StyleURL WMS 1.3.0 struct.
std::vector< BoundingBox > m_boundingBoxes
The BoundingBox WMS 1.3.0 struct.