Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsgmlschema.h 3 : : -------------------------------------- 4 : : Date : Sun Sep 16 12:19:55 AKDT 2007 5 : : Copyright : (C) 2007 by Gary E. Sherman 6 : : Email : sherman at mrcc dot com 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : #ifndef QGSGMLSCHEMA_H 16 : : #define QGSGMLSCHEMA_H 17 : : 18 : : #include "qgis_core.h" 19 : : #include <expat.h> 20 : : #include "qgis_sip.h" 21 : : #include "qgserror.h" 22 : : #include "qgsfields.h" 23 : : #include <list> 24 : : #include <set> 25 : : #include <stack> 26 : : #include <QPair> 27 : : #include <QByteArray> 28 : : #include <QDomElement> 29 : : #include <QStringList> 30 : : #include <QStack> 31 : : 32 : : class QgsRectangle; 33 : : class QgsCoordinateReferenceSystem; 34 : : class QgsFeature; 35 : : 36 : : /** 37 : : * \ingroup core 38 : : * \brief Description of feature class in GML 39 : : */ 40 : 0 : class CORE_EXPORT QgsGmlFeatureClass 41 : : { 42 : : public: 43 : : 44 : : /** 45 : : * Constructor for QgsGmlFeatureClass. 46 : : */ 47 : 0 : QgsGmlFeatureClass() = default; 48 : : QgsGmlFeatureClass( const QString &name, const QString &path ); 49 : : 50 : 0 : QList<QgsField> &fields() { return mFields; } 51 : : 52 : : int fieldIndex( const QString &name ); 53 : : 54 : : QString path() const { return mPath; } 55 : : 56 : 0 : QStringList &geometryAttributes() { return mGeometryAttributes; } 57 : : 58 : : private: 59 : : 60 : : /** 61 : : * Feature class name: 62 : : * 63 : : * - element name without NS or known prefix/suffix (_feature) 64 : : * - typeName attribute name 65 : : */ 66 : : QString mName; 67 : : 68 : : //QString mElementName; 69 : : 70 : : //! Dot separated path to element including the name 71 : : QString mPath; 72 : : 73 : : /* Fields */ 74 : : // Do not use QMap to keep original fields order. If it gets to performance, 75 : : // add a field index map 76 : : QList<QgsField> mFields; 77 : : 78 : : /* Geometry attribute */ 79 : : QStringList mGeometryAttributes; 80 : : }; 81 : : 82 : : /** 83 : : * \ingroup core 84 : : * \class QgsGmlSchema 85 : : */ 86 : : class CORE_EXPORT QgsGmlSchema : public QObject 87 : : { 88 : 0 : Q_OBJECT 89 : : public: 90 : : QgsGmlSchema(); 91 : : 92 : : //! Gets fields info from XSD 93 : : bool parseXSD( const QByteArray &xml ); 94 : : 95 : : /** 96 : : * Guess GML schema from data if XSD does not exist. 97 : : * Currently only recognizes UMN Mapserver GetFeatureInfo GML response. 98 : : * Supports only UTF-8, UTF-16, ISO-8859-1, US-ASCII XML encodings. 99 : : * \param data GML data 100 : : * \returns TRUE in case of success 101 : : */ 102 : : bool guessSchema( const QByteArray &data ); 103 : : 104 : : //! Gets list of dot separated paths to feature classes parsed from GML or XSD 105 : : QStringList typeNames() const; 106 : : 107 : : //! Gets fields for type/class name parsed from GML or XSD 108 : : QList<QgsField> fields( const QString &typeName ); 109 : : 110 : : //! Gets list of geometry attributes for type/class name 111 : : QStringList geometryAttributes( const QString &typeName ); 112 : : 113 : : //! Gets error if parseXSD() or guessSchema() failed 114 : : QgsError error() const { return mError; } 115 : : 116 : : private: 117 : : 118 : : enum ParseMode 119 : : { 120 : : None, 121 : : BoundingBox, 122 : : FeatureMembers, // gml:featureMembers 123 : : FeatureMember, // gml:featureMember 124 : : Feature, // feature element containing attrs and geo (inside gml:featureMember) 125 : : Attribute, 126 : : Geometry 127 : : }; 128 : : 129 : : //! XML handler methods 130 : : void startElement( const XML_Char *el, const XML_Char **attr ); 131 : : void endElement( const XML_Char *el ); 132 : : void characters( const XML_Char *chars, int len ); 133 : 0 : static void start( void *data, const XML_Char *el, const XML_Char **attr ) 134 : : { 135 : 0 : static_cast<QgsGmlSchema *>( data )->startElement( el, attr ); 136 : 0 : } 137 : 0 : static void end( void *data, const XML_Char *el ) 138 : : { 139 : 0 : static_cast<QgsGmlSchema *>( data )->endElement( el ); 140 : 0 : } 141 : 0 : static void chars( void *data, const XML_Char *chars, int len ) 142 : : { 143 : 0 : static_cast<QgsGmlSchema *>( data )->characters( chars, len ); 144 : 0 : } 145 : : // Add attribute or reset its type according to value of current feature 146 : : void addAttribute( const QString &name, const QString &value ); 147 : : 148 : : //helper routines 149 : : 150 : : /** 151 : : * Reads attribute as string 152 : : * \returns attribute value or an empty string if no such attribute 153 : : */ 154 : : QString readAttribute( const QString &attributeName, const XML_Char **attr ) const; 155 : : 156 : : //! Returns pointer to main window or 0 if it does not exist 157 : : QWidget *findMainWindow() const; 158 : : 159 : : //! Gets dom elements by path 160 : : QList<QDomElement> domElements( const QDomElement &element, const QString &path ); 161 : : 162 : : //! Gets dom element by path 163 : : QDomElement domElement( const QDomElement &element, const QString &path ); 164 : : 165 : : //! Filter list of elements by attribute value 166 : : QList<QDomElement> domElements( QList<QDomElement> &elements, const QString &attr, const QString &attrVal ); 167 : : 168 : : //! Gets dom element by path and attribute value 169 : : QDomElement domElement( const QDomElement &element, const QString &path, const QString &attr, const QString &attrVal ); 170 : : 171 : : //! Strip namespace from element name 172 : : QString stripNS( const QString &name ); 173 : : 174 : : /** 175 : : * Find GML base type for complex type of given name 176 : : * \param element input element 177 : : * \param name complex type name 178 : : * \returns name of GML base type without NS, e.g. AbstractFeatureType or empty string if not passed on GML type 179 : : */ 180 : : QString xsdComplexTypeGmlBaseType( const QDomElement &element, const QString &name ); 181 : : 182 : : //! Gets feature class information from complex type recursively 183 : : bool xsdFeatureClass( const QDomElement &element, const QString &typeName, QgsGmlFeatureClass &featureClass ); 184 : : 185 : : 186 : : //! Gets safely (if empty) top from mode stack 187 : 0 : ParseMode modeStackTop() { return mParseModeStack.isEmpty() ? None : mParseModeStack.top(); } 188 : : 189 : : //! Safely (if empty) pop from mode stack 190 : 0 : ParseMode modeStackPop() { return mParseModeStack.isEmpty() ? None : mParseModeStack.pop(); } 191 : : 192 : : //! Keep track about the most important nested elements 193 : : //std::stack<ParseMode> mParseModeStack; 194 : : QStack<ParseMode> mParseModeStack; 195 : : //! This contains the character data if an important element has been encountered 196 : : QString mStringCash; 197 : : QgsFeature *mCurrentFeature = nullptr; 198 : : QString mCurrentFeatureId; 199 : : int mFeatureCount = 0; 200 : : QString mAttributeName; 201 : : //! Coordinate separator for coordinate strings. Usually "," 202 : : QString mCoordinateSeparator; 203 : : //! Tuple separator for coordinate strings. Usually " " 204 : : QString mTupleSeparator; 205 : : 206 : : /* Schema information guessed/parsed from GML in getSchema() */ 207 : : 208 : : //! Depth level, root element is 0 209 : : int mLevel = 0; 210 : : 211 : : //! Skip all levels under this 212 : : int mSkipLevel; 213 : : 214 : : //! Path to current level 215 : : QStringList mParsePathStack; 216 : : 217 : : QString mCurrentFeatureName; 218 : : 219 : : // List of know geometries (Point, Multipoint,...) 220 : : QStringList mGeometryTypes; 221 : : 222 : : /* Feature classes map with element paths as keys */ 223 : : QMap<QString, QgsGmlFeatureClass> mFeatureClassMap; 224 : : 225 : : /* Error set if something failed */ 226 : : QgsError mError; 227 : : }; 228 : : 229 : : #endif