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 "memdataset.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() const override
73 : {
74 1160 : return OGRMemLayer::GetLayerDefn()->GetName();
75 : }
76 :
77 29 : OGRwkbGeometryType GetGeomType() const override
78 : {
79 29 : return wkbNone;
80 : }
81 :
82 10 : const OGRSpatialReference *GetSpatialRef() const override
83 : {
84 10 : return nullptr;
85 : }
86 :
87 459 : void ResetReading() override
88 : {
89 459 : Init();
90 459 : OGRMemLayer::ResetReading();
91 459 : }
92 :
93 : int TestCapability(const char *pszCap) const override;
94 :
95 84 : const CPLString &GetFilename() const
96 : {
97 84 : return osFilename;
98 : }
99 :
100 : /* For external usage. Mess with FID */
101 : OGRFeature *GetNextFeature() override;
102 : OGRFeature *GetFeature(GIntBig nFeatureId) override;
103 : OGRErr ISetFeature(OGRFeature *poFeature) override;
104 : OGRErr ISetFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature) override;
105 : OGRErr IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
106 : const int *panUpdatedFieldsIdx,
107 : int nUpdatedGeomFieldsCount,
108 : const int *panUpdatedGeomFieldsIdx,
109 : bool bUpdateStyleString) override;
110 : OGRErr DeleteFeature(GIntBig nFID) override;
111 :
112 23 : OGRErr SetNextByIndex(GIntBig nIndex) override
113 : {
114 23 : Init();
115 23 : return OGRMemLayer::SetNextByIndex(nIndex);
116 : }
117 :
118 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
119 : OGRErr ICreateFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature,
120 : GIntBig *pnFID) override;
121 :
122 5241 : const OGRFeatureDefn *GetLayerDefn() const override
123 : {
124 5241 : const_cast<OGRXLSXLayer *>(this)->Init();
125 5241 : return OGRMemLayer::GetLayerDefn();
126 : }
127 :
128 164 : GIntBig GetFeatureCount(int bForce) override
129 : {
130 164 : Init();
131 164 : return OGRMemLayer::GetFeatureCount(bForce);
132 : }
133 :
134 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
135 : int bApproxOK = TRUE) override;
136 :
137 0 : OGRErr DeleteField(int iField) override
138 : {
139 0 : Init();
140 0 : SetUpdated();
141 0 : return OGRMemLayer::DeleteField(iField);
142 : }
143 :
144 0 : OGRErr ReorderFields(int *panMap) override
145 : {
146 0 : Init();
147 0 : SetUpdated();
148 0 : return OGRMemLayer::ReorderFields(panMap);
149 : }
150 :
151 18 : virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
152 : int nFlagsIn) override
153 : {
154 18 : Init();
155 18 : SetUpdated();
156 18 : return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
157 : }
158 :
159 4 : const std::string &GetCols() const
160 : {
161 4 : return m_osCols;
162 : }
163 :
164 : OGRErr SyncToDisk() override;
165 :
166 : GDALDataset *GetDataset() override;
167 : };
168 :
169 : /************************************************************************/
170 : /* OGRXLSXDataSource */
171 : /************************************************************************/
172 : #define STACK_SIZE 5
173 :
174 : typedef enum
175 : {
176 : STATE_DEFAULT,
177 :
178 : /* for sharedString.xml */
179 : STATE_SI,
180 : STATE_T,
181 :
182 : /* for sheet?.xml */
183 : STATE_COLS,
184 : STATE_SHEETDATA,
185 : STATE_ROW,
186 : STATE_CELL,
187 : STATE_TEXTV,
188 : } HandlerStateEnum;
189 :
190 : typedef struct
191 : {
192 : HandlerStateEnum eVal;
193 : int nBeginDepth;
194 : } HandlerState;
195 :
196 : class XLSXFieldTypeExtended
197 : {
198 : public:
199 : OGRFieldType eType;
200 : bool bHasMS;
201 :
202 176 : XLSXFieldTypeExtended() : eType(OFTMaxType), bHasMS(false)
203 : {
204 176 : }
205 :
206 395 : explicit XLSXFieldTypeExtended(OGRFieldType eTypeIn, bool bHasMSIn = false)
207 395 : : eType(eTypeIn), bHasMS(bHasMSIn)
208 : {
209 395 : }
210 : };
211 :
212 : class OGRXLSXDataSource final : public GDALDataset
213 : {
214 : char *pszName;
215 : CPLString osPrefixedFilename;
216 : bool bUpdatable;
217 : bool bUpdated;
218 :
219 : int nLayers;
220 : OGRXLSXLayer **papoLayers;
221 : std::map<CPLString, CPLString> oMapRelsIdToTarget;
222 : std::set<std::string> m_oSetSheetId;
223 :
224 : void AnalyseSharedStrings(VSILFILE *fpSharedStrings);
225 : void AnalyseWorkbook(VSILFILE *fpWorkbook);
226 : void AnalyseWorkbookRels(VSILFILE *fpWorkbookRels);
227 : void AnalyseStyles(VSILFILE *fpStyles);
228 :
229 : std::vector<std::string> apoSharedStrings;
230 : std::string osCurrentString;
231 :
232 : bool bFirstLineIsHeaders;
233 : int bAutodetectTypes;
234 :
235 : XML_Parser oParser;
236 : bool bStopParsing;
237 : int nWithoutEventCounter;
238 : int nDataHandlerCounter;
239 : int nCurLine;
240 : int nCurCol;
241 :
242 : OGRXLSXLayer *poCurLayer;
243 : std::string m_osCols{};
244 :
245 : int nStackDepth;
246 : int nDepth;
247 : HandlerState stateStack[STACK_SIZE];
248 :
249 : CPLString osValueType;
250 : CPLString osValue;
251 :
252 : std::vector<std::string> apoFirstLineValues;
253 : std::vector<std::string> apoFirstLineTypes;
254 : std::vector<std::string> apoCurLineValues;
255 : std::vector<std::string> apoCurLineTypes;
256 :
257 : bool bInCellXFS;
258 : std::map<int, XLSXFieldTypeExtended> apoMapStyleFormats;
259 : std::vector<XLSXFieldTypeExtended> apoStyles;
260 :
261 : void PushState(HandlerStateEnum eVal);
262 : void startElementDefault(const char *pszName, const char **ppszAttr);
263 : void startElementTable(const char *pszName, const char **ppszAttr);
264 : void endElementTable(const char *pszName);
265 : void startElementCols(const char *pszName, const char **ppszAttr);
266 : void endElementCols(const char *pszName);
267 : void startElementRow(const char *pszName, const char **ppszAttr);
268 : void endElementRow(const char *pszName);
269 : void startElementCell(const char *pszName, const char **ppszAttr);
270 : void endElementCell(const char *pszName);
271 : void dataHandlerTextV(const char *data, int nLen);
272 :
273 : void DetectHeaderLine();
274 :
275 : OGRFieldType GetOGRFieldType(const char *pszValue, const char *pszValueType,
276 : OGRFieldSubType &eSubType);
277 :
278 : void DeleteLayer(const char *pszLayerName);
279 :
280 : public:
281 : explicit OGRXLSXDataSource(CSLConstList papszOpenOptionsIn);
282 : ~OGRXLSXDataSource() override;
283 : CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
284 :
285 : int Open(const char *pszFilename, const char *pszPrefixedFilename,
286 : VSILFILE *fpWorkbook, VSILFILE *fpWorkbookRels,
287 : VSILFILE *fpSharedStrings, VSILFILE *fpStyles, int bUpdate);
288 : int Create(const char *pszName, char **papszOptions);
289 :
290 : int GetLayerCount() const override;
291 : const OGRLayer *GetLayer(int) const override;
292 :
293 : int TestCapability(const char *) const override;
294 :
295 : OGRLayer *ICreateLayer(const char *pszName,
296 : const OGRGeomFieldDefn *poGeomFieldDefn,
297 : CSLConstList papszOptions) override;
298 :
299 : OGRErr DeleteLayer(int iLayer) override;
300 :
301 : CPLErr FlushCache(bool bAtClosing) override;
302 :
303 : void startElementCbk(const char *pszName, const char **ppszAttr);
304 : void endElementCbk(const char *pszName);
305 : void dataHandlerCbk(const char *data, int nLen);
306 :
307 : void startElementSSCbk(const char *pszName, const char **ppszAttr);
308 : void endElementSSCbk(const char *pszName);
309 : void dataHandlerSSCbk(const char *data, int nLen);
310 :
311 : void startElementWBRelsCbk(const char *pszName, const char **ppszAttr);
312 :
313 : void startElementWBCbk(const char *pszName, const char **ppszAttr);
314 :
315 : void startElementStylesCbk(const char *pszName, const char **ppszAttr);
316 : void endElementStylesCbk(const char *pszName);
317 :
318 : void BuildLayer(OGRXLSXLayer *poLayer);
319 :
320 1202 : bool GetUpdatable()
321 : {
322 1202 : return bUpdatable;
323 : }
324 :
325 12 : void SetUpdated()
326 : {
327 12 : bUpdated = true;
328 12 : }
329 : };
330 :
331 : } // namespace OGRXLSX
332 :
333 : #endif /* ndef OGR_XLSX_H_INCLUDED */
|