1 /******************************************************************************
2 * $Id: 8211createfromxml.cpp 27942 2014-11-11 00:57:41Z rouault $
3 *
4 * Project: ISO8211 library
5 * Purpose: Create a 8211 file from a XML dump file generated by "8211dump -xml"
6 * Author: Even Rouault <even dot rouault at mines-paris dot org>
7 *
8 ******************************************************************************
9 * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "cpl_minixml.h"
31 #include "iso8211.h"
32 #include <map>
33 #include <string>
34
35 CPL_CVSID("$Id: 8211createfromxml.cpp 27942 2014-11-11 00:57:41Z rouault $");
36
main(int nArgc,char * papszArgv[])37 int main(int nArgc, char* papszArgv[])
38 {
39 const char *pszFilename = NULL, *pszOutFilename = NULL;
40 DDFModule oModule;
41
42 /* -------------------------------------------------------------------- */
43 /* Check arguments. */
44 /* -------------------------------------------------------------------- */
45 for( int iArg = 1; iArg < nArgc; iArg++ )
46 {
47 if( pszFilename == NULL )
48 pszFilename = papszArgv[iArg];
49 else if( pszOutFilename == NULL )
50 pszOutFilename = papszArgv[iArg];
51 else
52 {
53 pszFilename = NULL;
54 break;
55 }
56 }
57
58 if( pszFilename == NULL )
59 {
60 printf( "Usage: 8211createfromxml filename.xml outfilename\n" );
61 exit( 1 );
62 }
63
64 CPLXMLNode* poRoot = CPLParseXMLFile( pszFilename );
65 if( poRoot == NULL )
66 {
67 fprintf(stderr, "Cannot parse XML file '%s'\n", pszFilename);
68 exit( 1 );
69 }
70
71 CPLXMLNode* poXMLDDFModule = CPLSearchXMLNode(poRoot, "=DDFModule");
72 if( poXMLDDFModule == NULL )
73 {
74 fprintf(stderr, "Cannot find DDFModule node in XML file '%s'\n", pszFilename);
75 exit( 1 );
76 }
77
78 /* Compute the size of the DDFField tag */
79 CPLXMLNode* psIter = poXMLDDFModule->psChild;
80 int nSizeFieldTag = 0;
81 while( psIter != NULL )
82 {
83 if( psIter->eType == CXT_Element &&
84 strcmp(psIter->pszValue, "DDFFieldDefn") == 0 )
85 {
86 const char* pszTag = CPLGetXMLValue(psIter, "tag", "");
87 if( nSizeFieldTag == 0 )
88 nSizeFieldTag = (int)strlen(pszTag);
89 else if( nSizeFieldTag != (int)strlen(pszTag) )
90 {
91 fprintf(stderr, "All fields have not the same tag size\n");
92 exit( 1 );
93 }
94 }
95 psIter = psIter->psNext;
96 }
97
98 char chInterchangeLevel = '3';
99 char chLeaderIden = 'L';
100 char chCodeExtensionIndicator = 'E';
101 char chVersionNumber = '1';
102 char chAppIndicator = ' ';
103 const char *pszExtendedCharSet = " ! ";
104 int nSizeFieldLength = 3;
105 int nSizeFieldPos = 4;
106
107 oModule.Initialize(chInterchangeLevel,
108 chLeaderIden,
109 chCodeExtensionIndicator,
110 chVersionNumber,
111 chAppIndicator,
112 pszExtendedCharSet,
113 nSizeFieldLength,
114 nSizeFieldPos,
115 nSizeFieldTag);
116
117 int bCreated = FALSE;
118
119 /* Create DDFFieldDefn and DDFRecord elements */
120 psIter = poXMLDDFModule->psChild;
121 while( psIter != NULL )
122 {
123 if( psIter->eType == CXT_Element &&
124 strcmp(psIter->pszValue, "DDFFieldDefn") == 0 )
125 {
126 DDFFieldDefn* poFDefn = new DDFFieldDefn();
127
128 DDF_data_struct_code eStructCode = dsc_elementary;
129 const char* pszStructCode = CPLGetXMLValue(psIter, "dataStructCode", "");
130 if( strcmp(pszStructCode, "elementary") == 0 ) eStructCode = dsc_elementary;
131 else if( strcmp(pszStructCode, "vector") == 0 ) eStructCode = dsc_vector;
132 else if( strcmp(pszStructCode, "array") == 0 ) eStructCode = dsc_array;
133 else if( strcmp(pszStructCode, "concatenated") == 0 ) eStructCode = dsc_concatenated;
134
135 DDF_data_type_code eTypeCode = dtc_char_string;
136 const char* pszTypeCode = CPLGetXMLValue(psIter, "dataTypeCode", "");
137 if( strcmp(pszTypeCode, "char_string") == 0 ) eTypeCode = dtc_char_string;
138 else if( strcmp(pszTypeCode, "implicit_point") == 0 ) eTypeCode = dtc_implicit_point;
139 else if( strcmp(pszTypeCode, "explicit_point") == 0 ) eTypeCode = dtc_explicit_point;
140 else if( strcmp(pszTypeCode, "explicit_point_scaled") == 0 ) eTypeCode = dtc_explicit_point_scaled;
141 else if( strcmp(pszTypeCode, "char_bit_string") == 0 ) eTypeCode = dtc_char_bit_string;
142 else if( strcmp(pszTypeCode, "bit_string") == 0 ) eTypeCode = dtc_bit_string;
143 else if( strcmp(pszTypeCode, "mixed_data_type") == 0 ) eTypeCode = dtc_mixed_data_type;
144
145 const char* pszFormatControls = CPLGetXMLValue(psIter, "formatControls", NULL);
146 if( eStructCode != dsc_elementary )
147 pszFormatControls = NULL;
148
149 const char* pszArrayDescr = CPLGetXMLValue(psIter, "arrayDescr", "");
150 if( eStructCode == dsc_vector )
151 pszArrayDescr = "";
152 else if( eStructCode == dsc_array )
153 pszArrayDescr = "*";
154
155 poFDefn->Create( CPLGetXMLValue(psIter, "tag", ""),
156 CPLGetXMLValue(psIter, "fieldName", ""),
157 pszArrayDescr,
158 eStructCode, eTypeCode,
159 pszFormatControls );
160
161 CPLXMLNode* psSubIter = psIter->psChild;
162 while( psSubIter != NULL )
163 {
164 if( psSubIter->eType == CXT_Element &&
165 strcmp(psSubIter->pszValue, "DDFSubfieldDefn") == 0 )
166 {
167 poFDefn->AddSubfield( CPLGetXMLValue(psSubIter, "name", ""),
168 CPLGetXMLValue(psSubIter, "format", "") );
169 }
170 psSubIter = psSubIter->psNext;
171 }
172
173 oModule.AddField( poFDefn );
174 }
175 else if( psIter->eType == CXT_Element &&
176 strcmp(psIter->pszValue, "DDFRecord") == 0 )
177 {
178 if( !bCreated )
179 {
180 oModule.Create( pszOutFilename );
181 bCreated = TRUE;
182 }
183
184 DDFRecord *poRec = new DDFRecord( &oModule );
185 std::map<std::string, int> oMapField;
186
187 CPLXMLNode* psSubIter = psIter->psChild;
188 while( psSubIter != NULL )
189 {
190 if( psSubIter->eType == CXT_Element &&
191 strcmp(psSubIter->pszValue, "DDFField") == 0 )
192 {
193 DDFField *poField;
194 const char* pszFieldName = CPLGetXMLValue(psSubIter, "name", "");
195 DDFFieldDefn* poFieldDefn = oModule.FindFieldDefn( pszFieldName );
196 if( poFieldDefn == NULL )
197 {
198 fprintf(stderr, "Can't find field '%s'\n", pszFieldName );
199 exit(1);
200 }
201
202 int nFieldOcc = oMapField[pszFieldName];
203 oMapField[pszFieldName] ++ ;
204
205 poField = poRec->AddField( poFieldDefn );
206 const char* pszValue = CPLGetXMLValue(psSubIter, "value", NULL);
207 if( pszValue != NULL && strncmp(pszValue, "0x", 2) == 0 )
208 {
209 pszValue += 2;
210 int nDataLen = (int)strlen(pszValue) / 2;
211 char* pabyData = (char*) malloc(nDataLen);
212 for(int i=0;i<nDataLen;i++)
213 {
214 char c;
215 int nHigh, nLow;
216 c = pszValue[2*i];
217 if( c >= 'A' && c <= 'F' )
218 nHigh = 10 + c - 'A';
219 else
220 nHigh = c - '0';
221 c = pszValue[2*i + 1];
222 if( c >= 'A' && c <= 'F' )
223 nLow = 10 + c - 'A';
224 else
225 nLow = c - '0';
226 pabyData[i] = (nHigh << 4) + nLow;
227 }
228 poRec->SetFieldRaw( poField, nFieldOcc, (const char *) pabyData, nDataLen );
229 free(pabyData);
230 }
231 else
232 {
233 CPLXMLNode* psSubfieldIter = psSubIter->psChild;
234 std::map<std::string, int> oMapSubfield;
235 while( psSubfieldIter != NULL )
236 {
237 if( psSubfieldIter->eType == CXT_Element &&
238 strcmp(psSubfieldIter->pszValue, "DDFSubfield") == 0 )
239 {
240 const char* pszSubfieldName = CPLGetXMLValue(psSubfieldIter, "name", "");
241 const char* pszSubfieldType = CPLGetXMLValue(psSubfieldIter, "type", "");
242 const char* pszSubfieldValue = CPLGetXMLValue(psSubfieldIter, NULL, "");
243 int nOcc = oMapSubfield[pszSubfieldName];
244 oMapSubfield[pszSubfieldName] ++ ;
245 if( strcmp(pszSubfieldType, "float") == 0 )
246 {
247 poRec->SetFloatSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
248 CPLAtof(pszSubfieldValue) );
249 }
250 else if( strcmp(pszSubfieldType, "integer") == 0 )
251 {
252 poRec->SetIntSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
253 atoi(pszSubfieldValue) );
254 }
255 else if( strcmp(pszSubfieldType, "string") == 0 )
256 {
257 poRec->SetStringSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
258 pszSubfieldValue );
259 }
260 else if( strcmp(pszSubfieldType, "binary") == 0 &&
261 strncmp(pszSubfieldValue, "0x", 2) == 0 )
262 {
263 pszSubfieldValue += 2;
264 int nDataLen = (int)strlen(pszSubfieldValue) / 2;
265 char* pabyData = (char*) malloc(nDataLen);
266 for(int i=0;i<nDataLen;i++)
267 {
268 char c;
269 int nHigh, nLow;
270 c = pszSubfieldValue[2*i];
271 if( c >= 'A' && c <= 'F' )
272 nHigh = 10 + c - 'A';
273 else
274 nHigh = c - '0';
275 c = pszSubfieldValue[2*i + 1];
276 if( c >= 'A' && c <= 'F' )
277 nLow = 10 + c - 'A';
278 else
279 nLow = c - '0';
280 pabyData[i] = (nHigh << 4) + nLow;
281 }
282 poRec->SetStringSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
283 pabyData, nDataLen );
284 free(pabyData);
285 }
286 }
287 psSubfieldIter = psSubfieldIter->psNext;
288 }
289 }
290 }
291 psSubIter = psSubIter->psNext;
292 }
293
294 poRec->Write();
295 delete poRec;
296 }
297
298 psIter = psIter->psNext;
299 }
300
301 CPLDestroyXMLNode(poRoot);
302
303 oModule.Close();
304
305 return 0;
306 }
307