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