Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: XLSX Translator
5 : * Purpose: Definition of classes for OGR OpenOfficeSpreadsheet .xlsx driver.
6 : * Author: Even Rouault, even dot rouault at spatialys.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2012, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #ifndef OGR_XLSX_H_INCLUDED
15 : #define OGR_XLSX_H_INCLUDED
16 :
17 : #include "ogrsf_frmts.h"
18 :
19 : #include "ogr_expat.h"
20 : #include "ogr_mem.h"
21 :
22 : #include <vector>
23 : #include <set>
24 : #include <string>
25 : #include <map>
26 :
27 : namespace OGRXLSX
28 : {
29 :
30 : /************************************************************************/
31 : /* OGRXLSXLayer */
32 : /************************************************************************/
33 :
34 : class OGRXLSXDataSource;
35 :
36 : class OGRXLSXLayer final : public OGRMemLayer
37 : {
38 : friend class OGRXLSXDataSource;
39 :
40 : bool bInit;
41 : OGRXLSXDataSource *poDS;
42 : CPLString osFilename;
43 : void Init();
44 : bool bUpdated;
45 : bool bHasHeaderLine;
46 : std::string m_osCols{};
47 : std::set<int> oSetFieldsOfUnknownType{};
48 :
49 : GIntBig TranslateFIDFromMemLayer(GIntBig nFID) const;
50 : GIntBig TranslateFIDToMemLayer(GIntBig nFID) const;
51 :
52 : public:
53 : OGRXLSXLayer(OGRXLSXDataSource *poDSIn, const char *pszFilename,
54 : const char *pszName, int bUpdateIn = FALSE);
55 :
56 : bool HasBeenUpdated() const
57 : {
58 : return bUpdated;
59 : }
60 :
61 : void SetUpdated(bool bUpdatedIn = true);
62 :
63 : bool GetHasHeaderLine() const
64 : {
65 : return bHasHeaderLine;
66 : }
67 :
68 60 : void SetHasHeaderLine(bool bIn)
69 : {
70 60 : bHasHeaderLine = bIn;
71 60 : }
72 :
73 1160 : const char *GetName() override
74 : {
75 1160 : return OGRMemLayer::GetLayerDefn()->GetName();
76 : }
77 :
78 29 : OGRwkbGeometryType GetGeomType() override
79 : {
80 29 : return wkbNone;
81 : }
82 :
83 10 : virtual OGRSpatialReference *GetSpatialRef() override
84 : {
85 10 : return nullptr;
86 : }
87 :
88 449 : void ResetReading() override
89 : {
90 449 : Init();
91 449 : OGRMemLayer::ResetReading();
92 449 : }
93 :
94 84 : const CPLString &GetFilename() const
95 : {
96 84 : return osFilename;
97 : }
98 :
99 : /* For external usage. Mess with FID */
100 : virtual OGRFeature *GetNextFeature() override;
101 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
102 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
103 : OGRErr IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
104 : const int *panUpdatedFieldsIdx,
105 : int nUpdatedGeomFieldsCount,
106 : const int *panUpdatedGeomFieldsIdx,
107 : bool bUpdateStyleString) override;
108 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
109 :
110 23 : virtual OGRErr SetNextByIndex(GIntBig nIndex) override
111 : {
112 23 : Init();
113 23 : return OGRMemLayer::SetNextByIndex(nIndex);
114 : }
115 :
116 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
117 :
118 5241 : OGRFeatureDefn *GetLayerDefn() override
119 : {
120 5241 : Init();
121 5241 : return OGRMemLayer::GetLayerDefn();
122 : }
123 :
124 164 : GIntBig GetFeatureCount(int bForce) override
125 : {
126 164 : Init();
127 164 : return OGRMemLayer::GetFeatureCount(bForce);
128 : }
129 :
130 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
131 : int bApproxOK = TRUE) override;
132 :
133 0 : virtual OGRErr DeleteField(int iField) override
134 : {
135 0 : Init();
136 0 : SetUpdated();
137 0 : return OGRMemLayer::DeleteField(iField);
138 : }
139 :
140 0 : virtual OGRErr ReorderFields(int *panMap) override
141 : {
142 0 : Init();
143 0 : SetUpdated();
144 0 : return OGRMemLayer::ReorderFields(panMap);
145 : }
146 :
147 18 : virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
148 : int nFlagsIn) override
149 : {
150 18 : Init();
151 18 : SetUpdated();
152 18 : return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
153 : }
154 :
155 445 : int TestCapability(const char *pszCap) override
156 : {
157 445 : Init();
158 445 : return OGRMemLayer::TestCapability(pszCap);
159 : }
160 :
161 4 : const std::string &GetCols() const
162 : {
163 4 : return m_osCols;
164 : }
165 :
166 : virtual OGRErr SyncToDisk() override;
167 :
168 : GDALDataset *GetDataset() override;
169 : };
170 :
171 : /************************************************************************/
172 : /* OGRXLSXDataSource */
173 : /************************************************************************/
174 : #define STACK_SIZE 5
175 :
176 : typedef enum
177 : {
178 : STATE_DEFAULT,
179 :
180 : /* for sharedString.xml */
181 : STATE_SI,
182 : STATE_T,
183 :
184 : /* for sheet?.xml */
185 : STATE_COLS,
186 : STATE_SHEETDATA,
187 : STATE_ROW,
188 : STATE_CELL,
189 : STATE_TEXTV,
190 : } HandlerStateEnum;
191 :
192 : typedef struct
193 : {
194 : HandlerStateEnum eVal;
195 : int nBeginDepth;
196 : } HandlerState;
197 :
198 : class XLSXFieldTypeExtended
199 : {
200 : public:
201 : OGRFieldType eType;
202 : bool bHasMS;
203 :
204 176 : XLSXFieldTypeExtended() : eType(OFTMaxType), bHasMS(false)
205 : {
206 176 : }
207 :
208 395 : explicit XLSXFieldTypeExtended(OGRFieldType eTypeIn, bool bHasMSIn = false)
209 395 : : eType(eTypeIn), bHasMS(bHasMSIn)
210 : {
211 395 : }
212 : };
213 :
214 : class OGRXLSXDataSource final : public GDALDataset
215 : {
216 : char *pszName;
217 : CPLString osPrefixedFilename;
218 : bool bUpdatable;
219 : bool bUpdated;
220 :
221 : int nLayers;
222 : OGRXLSXLayer **papoLayers;
223 : std::map<CPLString, CPLString> oMapRelsIdToTarget;
224 : std::set<std::string> m_oSetSheetId;
225 :
226 : void AnalyseSharedStrings(VSILFILE *fpSharedStrings);
227 : void AnalyseWorkbook(VSILFILE *fpWorkbook);
228 : void AnalyseWorkbookRels(VSILFILE *fpWorkbookRels);
229 : void AnalyseStyles(VSILFILE *fpStyles);
230 :
231 : std::vector<std::string> apoSharedStrings;
232 : std::string osCurrentString;
233 :
234 : bool bFirstLineIsHeaders;
235 : int bAutodetectTypes;
236 :
237 : XML_Parser oParser;
238 : bool bStopParsing;
239 : int nWithoutEventCounter;
240 : int nDataHandlerCounter;
241 : int nCurLine;
242 : int nCurCol;
243 :
244 : OGRXLSXLayer *poCurLayer;
245 : std::string m_osCols{};
246 :
247 : int nStackDepth;
248 : int nDepth;
249 : HandlerState stateStack[STACK_SIZE];
250 :
251 : CPLString osValueType;
252 : CPLString osValue;
253 :
254 : std::vector<std::string> apoFirstLineValues;
255 : std::vector<std::string> apoFirstLineTypes;
256 : std::vector<std::string> apoCurLineValues;
257 : std::vector<std::string> apoCurLineTypes;
258 :
259 : bool bInCellXFS;
260 : std::map<int, XLSXFieldTypeExtended> apoMapStyleFormats;
261 : std::vector<XLSXFieldTypeExtended> apoStyles;
262 :
263 : void PushState(HandlerStateEnum eVal);
264 : void startElementDefault(const char *pszName, const char **ppszAttr);
265 : void startElementTable(const char *pszName, const char **ppszAttr);
266 : void endElementTable(const char *pszName);
267 : void startElementCols(const char *pszName, const char **ppszAttr);
268 : void endElementCols(const char *pszName);
269 : void startElementRow(const char *pszName, const char **ppszAttr);
270 : void endElementRow(const char *pszName);
271 : void startElementCell(const char *pszName, const char **ppszAttr);
272 : void endElementCell(const char *pszName);
273 : void dataHandlerTextV(const char *data, int nLen);
274 :
275 : void DetectHeaderLine();
276 :
277 : OGRFieldType GetOGRFieldType(const char *pszValue, const char *pszValueType,
278 : OGRFieldSubType &eSubType);
279 :
280 : void DeleteLayer(const char *pszLayerName);
281 :
282 : public:
283 : explicit OGRXLSXDataSource(CSLConstList papszOpenOptionsIn);
284 : virtual ~OGRXLSXDataSource();
285 : CPLErr Close() override;
286 :
287 : int Open(const char *pszFilename, const char *pszPrefixedFilename,
288 : VSILFILE *fpWorkbook, VSILFILE *fpWorkbookRels,
289 : VSILFILE *fpSharedStrings, VSILFILE *fpStyles, int bUpdate);
290 : int Create(const char *pszName, char **papszOptions);
291 :
292 : virtual int GetLayerCount() override;
293 : virtual OGRLayer *GetLayer(int) override;
294 :
295 : virtual int TestCapability(const char *) override;
296 :
297 : OGRLayer *ICreateLayer(const char *pszName,
298 : const OGRGeomFieldDefn *poGeomFieldDefn,
299 : CSLConstList papszOptions) override;
300 :
301 : virtual OGRErr DeleteLayer(int iLayer) override;
302 :
303 : virtual CPLErr FlushCache(bool bAtClosing) override;
304 :
305 : void startElementCbk(const char *pszName, const char **ppszAttr);
306 : void endElementCbk(const char *pszName);
307 : void dataHandlerCbk(const char *data, int nLen);
308 :
309 : void startElementSSCbk(const char *pszName, const char **ppszAttr);
310 : void endElementSSCbk(const char *pszName);
311 : void dataHandlerSSCbk(const char *data, int nLen);
312 :
313 : void startElementWBRelsCbk(const char *pszName, const char **ppszAttr);
314 :
315 : void startElementWBCbk(const char *pszName, const char **ppszAttr);
316 :
317 : void startElementStylesCbk(const char *pszName, const char **ppszAttr);
318 : void endElementStylesCbk(const char *pszName);
319 :
320 : void BuildLayer(OGRXLSXLayer *poLayer);
321 :
322 1202 : bool GetUpdatable()
323 : {
324 1202 : return bUpdatable;
325 : }
326 :
327 12 : void SetUpdated()
328 : {
329 12 : bUpdated = true;
330 12 : }
331 : };
332 :
333 : } // namespace OGRXLSX
334 :
335 : #endif /* ndef OGR_XLSX_H_INCLUDED */
|