Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Godar, Marton | |
11 | * Kovacs, Ferenc | |
12 | * Raduly, Csaba | |
13 | * Szabo, Bence Janos | |
14 | * | |
15 | ******************************************************************************/ | |
970ed795 EL |
16 | #include "XMLParser.hh" |
17 | #include "TTCN3Module.hh" | |
18 | #include "SimpleType.hh" | |
19 | #include "ComplexType.hh" | |
20 | ||
21 | #include "GeneralFunctions.hh" | |
22 | ||
23 | #include <cstring> // for using "memset" function | |
24 | #include <cstdio> | |
25 | #include <cerrno> | |
26 | #include <climits> | |
27 | #ifndef ULLONG_MAX | |
28 | #define ULLONG_MAX 18446744073709551615ULL | |
29 | #endif | |
30 | #ifndef LLONG_MIN | |
31 | #define LLONG_MIN -9223372036854775808LL | |
32 | #endif | |
33 | #ifndef LLONG_MAX | |
34 | #define LLONG_MAX 9223372036854775807LL | |
35 | #endif | |
36 | ||
37 | extern bool V_flag_used; | |
38 | extern bool w_flag_used; | |
39 | extern bool x_flag_used; | |
40 | ||
41 | bool XMLParser::suspended = false; | |
42 | unsigned int XMLParser::num_errors = 0; | |
43 | unsigned int XMLParser::num_warnings = 0; | |
44 | ||
970ed795 | 45 | XMLParser::XMLParser(const char * a_filename) |
3abe9331 | 46 | : module(NULL) // get value with 'connectWithModule()' method |
47 | , filename(a_filename) // includes the path of the file | |
48 | , parser(NULL) | |
49 | , context(NULL) | |
50 | , parserCheckingXML(NULL) | |
51 | , contextCheckingXML(NULL) | |
52 | , contextCheckingXSD(NULL) | |
53 | , actualDepth(0) | |
54 | , actualTagName(n_NOTSET) | |
55 | , actualTagAttributes(this) | |
56 | , parentTagNames() | |
57 | , inside_annotation(){ | |
970ed795 EL |
58 | xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader); |
59 | ||
3abe9331 | 60 | parserCheckingXML = (xmlSAXHandler *) malloc(sizeof (xmlSAXHandler)); |
61 | memset(parserCheckingXML, 0, sizeof (xmlSAXHandler)); | |
62 | parserCheckingXML->initialized = XML_SAX2_MAGIC; | |
63 | parserCheckingXML->warning = warningHandler; | |
64 | parserCheckingXML->error = errorHandler; | |
970ed795 EL |
65 | contextCheckingXML = xmlCreateFileParserCtxt(a_filename); |
66 | if (!contextCheckingXML) { | |
67 | fprintf(stderr, | |
68 | "ERROR:\n" | |
69 | "Creating XML syntax checker has failed.\n"); | |
70 | ++num_errors; | |
71 | return; | |
72 | } | |
73 | contextCheckingXML->sax = parserCheckingXML; | |
74 | ||
3abe9331 | 75 | if (!x_flag_used) { |
970ed795 EL |
76 | contextCheckingXSD = xmlSchemaNewParserCtxt(a_filename); |
77 | if (!contextCheckingXSD) { | |
78 | fprintf(stderr, | |
79 | "ERROR:\n" | |
80 | "Creating XSD validator has failed.\n"); | |
81 | ++num_errors; | |
82 | return; | |
83 | } | |
84 | xmlSchemaSetParserErrors(contextCheckingXSD, errorHandler, warningHandler, 0); | |
85 | } | |
86 | ||
3abe9331 | 87 | parser = (xmlSAXHandler *) malloc(sizeof (xmlSAXHandler)); |
88 | memset(parser, 0, sizeof (xmlSAXHandler)); | |
970ed795 | 89 | parser->initialized = XML_SAX2_MAGIC; |
3abe9331 | 90 | parser->startElementNs = (startElementNsSAX2Func) wrapper_to_call_startelement_h; |
91 | parser->endElementNs = (endElementNsSAX2Func) wrapper_to_call_endelement_h; | |
92 | parser->characters = (charactersSAXFunc) wrapper_to_call_characterdata_h; | |
93 | parser->comment = (commentSAXFunc) wrapper_to_call_comment_h; | |
970ed795 EL |
94 | |
95 | context = xmlCreateFileParserCtxt(filename.c_str()); | |
96 | if (!context) { | |
97 | fprintf(stderr, | |
98 | "ERROR:\n" | |
99 | "Creating parser for file '%s' has failed.\n", filename.c_str()); | |
100 | ++num_errors; | |
101 | return; | |
102 | } | |
103 | context->sax = parser; | |
104 | context->userData = this; | |
105 | } | |
106 | ||
3abe9331 | 107 | XMLParser::~XMLParser() { |
970ed795 | 108 | context->sax = NULL; |
3abe9331 | 109 | xmlFreeDoc(context->myDoc); |
970ed795 EL |
110 | contextCheckingXML->sax = NULL; |
111 | free(parser); | |
112 | free(parserCheckingXML); | |
3abe9331 | 113 | if (context) { |
114 | xmlFreeParserCtxt(context); | |
115 | } | |
116 | if (contextCheckingXML) { | |
117 | xmlFreeParserCtxt(contextCheckingXML); | |
118 | } | |
119 | if (contextCheckingXSD) { | |
120 | xmlSchemaFreeParserCtxt(contextCheckingXSD); | |
121 | } | |
970ed795 EL |
122 | } |
123 | ||
3abe9331 | 124 | void XMLParser::checkSyntax() { |
970ed795 EL |
125 | xmlParseDocument(contextCheckingXML); |
126 | } | |
127 | ||
3abe9331 | 128 | void XMLParser::validate() { |
970ed795 EL |
129 | if (!x_flag_used) { |
130 | xmlSchemaPtr schema = xmlSchemaParse(contextCheckingXSD); | |
131 | if (schema) { | |
132 | xmlSchemaValidCtxtPtr validator = xmlSchemaNewValidCtxt(schema); | |
133 | if (validator) { | |
134 | // do not use this->context! | |
135 | xmlParserCtxtPtr newcontext = xmlNewParserCtxt(); | |
136 | xmlDocPtr doc = xmlCtxtReadFile(newcontext, filename.c_str(), NULL, 0); | |
137 | if (doc) { | |
138 | // Don't try this, it always fails | |
139 | //int result = xmlSchemaValidateDoc(validator, doc); | |
140 | //(void)result; // 0=ok, errorcode > 0, intrnal error == -1 | |
141 | xmlFreeDoc(doc); | |
142 | } | |
143 | xmlSchemaFreeValidCtxt(validator); | |
3abe9331 | 144 | xmlFreeParserCtxt(newcontext); |
970ed795 EL |
145 | } |
146 | xmlSchemaFree(schema); | |
147 | } | |
148 | } | |
149 | } | |
150 | ||
3abe9331 | 151 | void XMLParser::startConversion(TTCN3Module * a_module) { |
970ed795 EL |
152 | module = a_module; |
153 | xmlParseDocument(context); | |
154 | } | |
155 | ||
156 | void XMLParser::wrapper_to_call_startelement_h(XMLParser *self, const xmlChar * localname, const xmlChar *, const xmlChar *, | |
3abe9331 | 157 | int nb_namespaces, const xmlChar ** namespaces, const int nb_attributes, int, const xmlChar ** attributes) { |
970ed795 EL |
158 | self->startelementHandler(localname, nb_namespaces, namespaces, nb_attributes, attributes); |
159 | } | |
160 | ||
3abe9331 | 161 | void XMLParser::wrapper_to_call_endelement_h(XMLParser *self, const xmlChar * localname, const xmlChar *, const xmlChar *) { |
970ed795 EL |
162 | self->endelementHandler(localname); |
163 | } | |
164 | ||
3abe9331 | 165 | void XMLParser::wrapper_to_call_comment_h(XMLParser *self, const xmlChar * value) { |
970ed795 EL |
166 | self->commentHandler(value); |
167 | } | |
168 | ||
3abe9331 | 169 | void XMLParser::wrapper_to_call_characterdata_h(XMLParser *self, const xmlChar * ch, int len) { |
970ed795 EL |
170 | self->characterdataHandler(ch, len); |
171 | } | |
172 | ||
3abe9331 | 173 | void XMLParser::warningHandler(void *, const char *, ...) { |
174 | if (w_flag_used) { | |
175 | return; | |
176 | } | |
970ed795 EL |
177 | |
178 | xmlErrorPtr error = xmlGetLastError(); | |
179 | ||
3abe9331 | 180 | if (error->file == NULL) { |
970ed795 EL |
181 | fprintf(stderr, |
182 | "WARNING:\n" | |
183 | "%s", | |
184 | error->message); | |
3abe9331 | 185 | } else { |
970ed795 EL |
186 | fprintf(stderr, |
187 | "WARNING:\n" | |
188 | "%s (in line %d): " | |
189 | "%s", | |
190 | error->file, | |
191 | error->line, | |
192 | error->message); | |
3abe9331 | 193 | ++num_warnings; |
194 | } | |
970ed795 EL |
195 | } |
196 | ||
3abe9331 | 197 | void XMLParser::errorHandler(void *, const char *, ...) { |
970ed795 EL |
198 | xmlErrorPtr error = xmlGetLastError(); |
199 | ||
3abe9331 | 200 | if (error->code == XML_SCHEMAP_SRC_RESOLVE) { |
201 | return; | |
202 | } | |
203 | if (error->code == XML_SCHEMAP_COS_ALL_LIMITED) { | |
204 | return; | |
205 | } | |
970ed795 EL |
206 | |
207 | switch (error->level) { | |
3abe9331 | 208 | case XML_ERR_ERROR: |
209 | fputs("ERROR:\n", stderr); | |
210 | break; | |
211 | case XML_ERR_FATAL: | |
212 | fputs("FATAL ERROR:\n", stderr); | |
213 | break; | |
214 | default: // warning or no error, can't happen (famous last words) | |
215 | break; | |
970ed795 EL |
216 | } |
217 | ||
218 | if (error->file != NULL) { | |
219 | fprintf(stderr, "%s (in line %d): ", error->file, error->line); | |
220 | } | |
221 | ||
222 | fputs(error->message, stderr); // libxml2 supplies a trailing \n | |
223 | ++num_errors; | |
224 | } | |
225 | ||
226 | void XMLParser::startelementHandler(const xmlChar * localname, | |
3abe9331 | 227 | int nb_namespaces, const xmlChar ** namespaces, int nb_attributes, const xmlChar ** attributes) { |
228 | fillUpActualTagName((const char *) localname, startElement); | |
229 | fillUpActualTagAttributes((const char **) attributes, nb_attributes); | |
970ed795 | 230 | |
3abe9331 | 231 | switch (module->getActualXsdConstruct()) { |
232 | case c_unknown: | |
233 | { | |
234 | switch (actualTagName) { | |
235 | case n_schema: | |
236 | { | |
237 | module->setActualXsdConstruct(c_schema); | |
238 | ||
239 | module->loadValuesFromXMLDeclaration((const char *) context->version, | |
240 | (const char *) context->encoding, context->standalone); | |
241 | ||
242 | List<NamespaceType> declaredNamespaces; | |
243 | for (int i = 0; i < nb_namespaces * 2; i = i + 2) { | |
244 | NamespaceType tmp_ns_pair; | |
245 | ||
246 | if (namespaces[i] != NULL) { | |
247 | tmp_ns_pair.prefix = (const char*) namespaces[i]; | |
248 | } | |
249 | // else leave it as empty string | |
250 | ||
251 | if (namespaces[i + 1] != NULL) { | |
252 | tmp_ns_pair.uri = (const char*) namespaces[i + 1]; | |
253 | } | |
254 | // else leave it as empty string | |
255 | ||
256 | declaredNamespaces.push_back(tmp_ns_pair); | |
257 | } | |
258 | ||
259 | module->loadValuesFromSchemaTag(actualTagAttributes.targetNamespace, declaredNamespaces, | |
260 | actualTagAttributes.elementFormDefault, actualTagAttributes.attributeFormDefault, | |
261 | actualTagAttributes.blockDefault); | |
262 | break; | |
263 | } | |
264 | default: | |
265 | break; | |
970ed795 | 266 | } |
970ed795 EL |
267 | break; |
268 | } | |
970ed795 | 269 | |
3abe9331 | 270 | case c_schema: |
970ed795 | 271 | { |
3abe9331 | 272 | switch (actualTagName) { |
273 | case n_simpleType: | |
274 | module->addMainType(c_simpleType); | |
275 | break; | |
276 | case n_element: | |
277 | module->addMainType(c_element); | |
278 | break; | |
279 | case n_attribute: | |
280 | module->addMainType(c_attribute); | |
281 | break; | |
282 | case n_complexType: | |
283 | module->addMainType(c_complexType); | |
284 | break; | |
285 | case n_group: | |
286 | module->addMainType(c_group); | |
287 | break; | |
288 | case n_attributeGroup: | |
289 | module->addMainType(c_attributeGroup); | |
290 | break; | |
291 | case n_include: | |
292 | module->addMainType(c_include); | |
293 | break; | |
294 | case n_import: | |
295 | module->addMainType(c_import); | |
296 | break; | |
297 | default: | |
298 | break; | |
299 | } | |
970ed795 | 300 | break; |
3abe9331 | 301 | } |
302 | ||
970ed795 | 303 | default: |
3abe9331 | 304 | if (module->hasDefinedMainType()) { |
305 | if(actualTagName == n_annotation || | |
306 | actualTagName == n_appinfo || | |
307 | actualTagName == n_documentation){ | |
308 | inside_annotation.push_back(actualTagName); | |
309 | module->getLastMainType().loadWithValues(); | |
310 | }else if(inside_annotation.empty()){ | |
311 | module->getLastMainType().loadWithValues(); | |
312 | } | |
313 | } | |
970ed795 | 314 | break; |
3abe9331 | 315 | } |
970ed795 | 316 | |
3abe9331 | 317 | //Standard section 7.1.1 |
318 | if (!actualTagAttributes.id.empty()) { | |
319 | ConstructType type = module->getActualXsdConstruct(); | |
320 | module->addMainType(c_idattrib); | |
321 | module->setActualXsdConstruct(type); | |
970ed795 EL |
322 | } |
323 | ||
324 | ++actualDepth; | |
325 | parentTagNames.push_back(actualTagName); | |
326 | } | |
327 | ||
3abe9331 | 328 | void XMLParser::endelementHandler(const xmlChar * localname) { |
329 | fillUpActualTagName((const char *) localname, endElement); | |
330 | ||
331 | bool modify = false; | |
332 | TagName tag = parentTagNames.back(); | |
333 | //After some tags there is no need to call modifyValues | |
334 | if (tag == n_element || | |
335 | tag == n_all || | |
336 | tag == n_choice || | |
337 | tag == n_group || | |
338 | tag == n_attributeGroup || | |
339 | tag == n_extension || | |
340 | tag == n_simpleType || | |
341 | tag == n_simpleContent || | |
342 | tag == n_sequence || | |
343 | tag == n_complexType || | |
344 | tag == n_complexContent || | |
345 | tag == n_attribute || | |
346 | tag == n_anyAttribute | |
347 | ) { | |
348 | modify = true; | |
349 | } | |
350 | ||
351 | if(tag == n_annotation || | |
352 | tag == n_appinfo || | |
353 | tag == n_documentation){ | |
354 | inside_annotation.pop_back(); | |
355 | } | |
2b00ec8e | 356 | |
357 | if(tag == n_list) { | |
358 | if(module->hasDefinedMainType()) { | |
359 | SimpleType& st = (SimpleType&)(module->getLastMainType()); | |
360 | if(st.getXsdtype() == n_NOTSET){ | |
361 | st.setMode(SimpleType::restrictionAfterListMode); | |
362 | } | |
363 | } | |
364 | } | |
970ed795 EL |
365 | |
366 | --actualDepth; | |
3abe9331 | 367 | if (actualDepth == 0 || actualDepth == 1) { |
368 | module->setActualXsdConstruct(c_schema); | |
369 | } | |
970ed795 | 370 | |
3abe9331 | 371 | if (module->hasDefinedMainType() && modify) { |
372 | module->getLastMainType().modifyValues(); | |
373 | } | |
374 | parentTagNames.pop_back(); | |
970ed795 EL |
375 | } |
376 | ||
3abe9331 | 377 | void XMLParser::commentHandler(const xmlChar * text) { |
378 | Mstring comment((const char *) text); | |
970ed795 EL |
379 | comment.removeWSfromBegin(); |
380 | comment.removeWSfromEnd(); | |
3abe9331 | 381 | if (comment.empty()) { |
382 | return; | |
383 | } | |
970ed795 EL |
384 | |
385 | if (module->getActualXsdConstruct() == c_schema) { | |
386 | module->addMainType(c_annotation); | |
387 | module->setActualXsdConstruct(c_schema); // actualXsdConstruct was set to c_annotation | |
388 | } | |
389 | ||
3abe9331 | 390 | if (module->hasDefinedMainType()) { |
391 | module->getLastMainType().addComment(comment); | |
392 | } | |
970ed795 EL |
393 | } |
394 | ||
3abe9331 | 395 | void XMLParser::characterdataHandler(const xmlChar * text, const int length) { |
396 | if (suspended) { | |
397 | return; | |
398 | } | |
970ed795 | 399 | |
3abe9331 | 400 | char * temp = (char *) Malloc(length + 1); |
970ed795 EL |
401 | memcpy(temp, text, length); |
402 | temp[length] = '\0'; | |
403 | Mstring comment(temp); | |
404 | Free(temp); | |
405 | ||
406 | comment.removeWSfromBegin(); | |
407 | comment.removeWSfromEnd(); | |
3abe9331 | 408 | if (comment.empty()) { |
409 | return; | |
410 | } | |
970ed795 EL |
411 | |
412 | if (module->getActualXsdConstruct() == c_schema) { | |
413 | module->addMainType(c_annotation); | |
414 | } | |
3abe9331 | 415 | if (module->hasDefinedMainType()) { |
416 | module->getLastMainType().addComment(comment); | |
417 | } | |
970ed795 EL |
418 | } |
419 | ||
3abe9331 | 420 | void XMLParser::fillUpActualTagName(const char * localname, const tagMode mode) { |
970ed795 EL |
421 | Mstring name_s(localname); |
422 | ||
423 | if (name_s == "all") | |
424 | actualTagName = n_all; | |
425 | else if (name_s == "annotation") | |
426 | actualTagName = n_annotation; | |
427 | else if (name_s == "any") | |
428 | actualTagName = n_any; | |
429 | else if (name_s == "anyAttribute") | |
430 | actualTagName = n_anyAttribute; | |
431 | else if (name_s == "appinfo") { | |
432 | actualTagName = n_appinfo; | |
3abe9331 | 433 | switch (mode) { |
434 | case startElement: | |
435 | suspended = true; | |
436 | break; | |
437 | case endElement: | |
438 | suspended = false; | |
439 | break; | |
440 | default: | |
441 | break; | |
970ed795 | 442 | } |
3abe9331 | 443 | } else if (name_s == "attribute") |
970ed795 EL |
444 | actualTagName = n_attribute; |
445 | else if (name_s == "attributeGroup") | |
446 | actualTagName = n_attributeGroup; | |
447 | else if (name_s == "choice") | |
448 | actualTagName = n_choice; | |
449 | else if (name_s == "complexContent") | |
450 | actualTagName = n_complexContent; | |
451 | else if (name_s == "complexType") | |
452 | actualTagName = n_complexType; | |
453 | else if (name_s == "definition") | |
454 | actualTagName = n_definition; | |
455 | else if (name_s == "documentation") | |
456 | actualTagName = n_documentation; | |
457 | else if (name_s == "element") | |
458 | actualTagName = n_element; | |
459 | else if (name_s == "enumeration") | |
460 | actualTagName = n_enumeration; | |
461 | else if (name_s == "extension") | |
462 | actualTagName = n_extension; | |
463 | else if (name_s == "field") { | |
464 | actualTagName = n_field; | |
465 | if (mode == startElement) { | |
466 | printWarning(filename, xmlSAX2GetLineNumber(context), | |
467 | Mstring("The 'field' tag is ignored by the standard.")); | |
468 | ++num_warnings; | |
469 | } | |
3abe9331 | 470 | } else if (name_s == "fractionDigits") { |
970ed795 | 471 | actualTagName = n_fractionDigits; |
3abe9331 | 472 | if (mode == startElement) { |
473 | printWarning(filename, xmlSAX2GetLineNumber(context), | |
474 | Mstring("The 'fractionDigits' tag is currently not supported.")); | |
475 | ++num_warnings; | |
476 | } | |
477 | } else if (name_s == "group") | |
970ed795 EL |
478 | actualTagName = n_group; |
479 | else if (name_s == "import") | |
480 | actualTagName = n_import; | |
481 | else if (name_s == "include") | |
482 | actualTagName = n_include; | |
483 | else if (name_s == "key") { | |
484 | actualTagName = n_key; | |
485 | if (mode == startElement) { | |
486 | printWarning(filename, xmlSAX2GetLineNumber(context), | |
487 | Mstring("The 'key' tag is ignored by the standard.")); | |
488 | ++num_warnings; | |
489 | } | |
3abe9331 | 490 | } else if (name_s == "keyref") { |
970ed795 EL |
491 | actualTagName = n_keyref; |
492 | if (mode == startElement) { | |
493 | printWarning(filename, xmlSAX2GetLineNumber(context), | |
494 | Mstring("The 'keyref' tag ignored by the standard.")); | |
495 | ++num_warnings; | |
496 | } | |
3abe9331 | 497 | } else if (name_s == "length") |
970ed795 EL |
498 | actualTagName = n_length; |
499 | else if (name_s == "label") | |
500 | actualTagName = n_label; | |
501 | else if (name_s == "list") | |
502 | actualTagName = n_list; | |
503 | else if (name_s == "maxExclusive") | |
504 | actualTagName = n_maxExclusive; | |
505 | else if (name_s == "maxInclusive") | |
506 | actualTagName = n_maxInclusive; | |
507 | else if (name_s == "maxLength") | |
508 | actualTagName = n_maxLength; | |
509 | else if (name_s == "minExclusive") | |
510 | actualTagName = n_minExclusive; | |
511 | else if (name_s == "minInclusive") | |
512 | actualTagName = n_minInclusive; | |
513 | else if (name_s == "minLength") | |
514 | actualTagName = n_minLength; | |
515 | else if (name_s == "notation") | |
516 | ; | |
517 | else if (name_s == "pattern") | |
518 | actualTagName = n_pattern; | |
519 | else if (name_s == "redefine") | |
520 | actualTagName = n_redefine; | |
521 | else if (name_s == "restriction") | |
522 | actualTagName = n_restriction; | |
523 | else if (name_s == "schema") | |
524 | actualTagName = n_schema; | |
525 | else if (name_s == "selector") { | |
526 | actualTagName = n_selector; | |
527 | if (mode == startElement) { | |
528 | printWarning(filename, xmlSAX2GetLineNumber(context), | |
529 | Mstring("The 'selector' tag ignored by the standard.")); | |
530 | ++num_warnings; | |
531 | } | |
3abe9331 | 532 | } else if (name_s == "sequence") |
970ed795 EL |
533 | actualTagName = n_sequence; |
534 | else if (name_s == "simpleContent") | |
535 | actualTagName = n_simpleContent; | |
536 | else if (name_s == "simpleType") | |
537 | actualTagName = n_simpleType; | |
538 | else if (name_s == "totalDigits") | |
539 | actualTagName = n_totalDigits; | |
540 | else if (name_s == "union") | |
541 | actualTagName = n_union; | |
542 | else if (name_s == "unique") { | |
543 | actualTagName = n_unique; | |
544 | if (mode == startElement) { | |
545 | printWarning(filename, xmlSAX2GetLineNumber(context), | |
546 | Mstring("The 'unique' tag ignored by the standard.")); | |
547 | ++num_warnings; | |
548 | } | |
3abe9331 | 549 | } else if (name_s == "whiteSpace") |
970ed795 EL |
550 | actualTagName = n_whiteSpace; |
551 | } | |
552 | ||
3abe9331 | 553 | void XMLParser::fillUpActualTagAttributes(const char ** attributes, const int att_count) { |
554 | ||
970ed795 EL |
555 | struct attribute_data { |
556 | const char * name; | |
557 | const char * prefix; | |
558 | const char * uri; | |
559 | const char * value_start; | |
560 | const char * value_end; | |
561 | }; | |
3abe9331 | 562 | attribute_data * ad = (attribute_data *) attributes; |
970ed795 EL |
563 | |
564 | Mstring * att_name_s = new Mstring[att_count]; | |
565 | Mstring * att_value_s = new Mstring[att_count]; | |
566 | TagAttributeName * att_name_e = new TagAttributeName[att_count]; | |
567 | ||
568 | for (int i = 0; i != att_count; ++i) { | |
569 | att_name_s[i] = ad[i].name; | |
570 | att_value_s[i] = Mstring(ad[i].value_end - ad[i].value_start, ad[i].value_start); | |
571 | ||
572 | att_name_e[i] = a_NOTSET; | |
573 | if (att_name_s[i] == "abstract") { | |
574 | att_name_e[i] = a_abstract; | |
3abe9331 | 575 | } else if (att_name_s[i] == "attributeFormDefault") |
970ed795 EL |
576 | att_name_e[i] = a_attributeFormDefault; |
577 | else if (att_name_s[i] == "base") | |
578 | att_name_e[i] = a_base; | |
579 | else if (att_name_s[i] == "block") { | |
580 | att_name_e[i] = a_block; | |
3abe9331 | 581 | } else if (att_name_s[i] == "blockDefault"){ |
582 | att_name_e[i] = a_blockDefault; | |
583 | } else if (att_name_s[i] == "default") | |
970ed795 EL |
584 | att_name_e[i] = a_default; |
585 | else if (att_name_s[i] == "elementFormDefault") | |
586 | att_name_e[i] = a_elementFormDefault; | |
587 | else if (att_name_s[i] == "final") { | |
588 | att_name_e[i] = a_final; // no effect on the output | |
3abe9331 | 589 | } else if (att_name_s[i] == "finalDefault") |
970ed795 EL |
590 | ; |
591 | else if (att_name_s[i] == "fixed") | |
592 | att_name_e[i] = a_fixed; | |
593 | else if (att_name_s[i] == "form") | |
594 | att_name_e[i] = a_form; | |
595 | else if (att_name_s[i] == "id") | |
596 | att_name_e[i] = a_id; | |
597 | else if (att_name_s[i] == "itemType") | |
598 | att_name_e[i] = a_itemType; | |
599 | else if (att_name_s[i] == "lang") | |
600 | ; | |
601 | else if (att_name_s[i] == "maxOccurs") | |
602 | att_name_e[i] = a_maxOccurs; | |
603 | else if (att_name_s[i] == "memberTypes") | |
604 | att_name_e[i] = a_memberTypes; | |
605 | else if (att_name_s[i] == "minOccurs") | |
606 | att_name_e[i] = a_minOccurs; | |
607 | else if (att_name_s[i] == "mixed") | |
608 | att_name_e[i] = a_mixed; | |
609 | else if (att_name_s[i] == "name") | |
610 | att_name_e[i] = a_name; | |
611 | else if (att_name_s[i] == "namespace") | |
612 | att_name_e[i] = a_namespace; | |
613 | else if (att_name_s[i] == "nillable") | |
614 | att_name_e[i] = a_nillable; | |
615 | else if (att_name_s[i] == "processContents") { | |
616 | att_name_e[i] = a_processContents; | |
617 | // silently ignored | |
3abe9331 | 618 | } else if (att_name_s[i] == "ref") |
970ed795 EL |
619 | att_name_e[i] = a_ref; |
620 | else if (att_name_s[i] == "schemaLocation") | |
621 | att_name_e[i] = a_schemaLocation; | |
622 | else if (att_name_s[i] == "substitutionGroup") { | |
623 | att_name_e[i] = a_substitutionGroup; | |
3abe9331 | 624 | } else if (att_name_s[i] == "targetNamespace") |
970ed795 EL |
625 | att_name_e[i] = a_targetNamespace; |
626 | else if (att_name_s[i] == "type") | |
627 | att_name_e[i] = a_type; | |
628 | else if (att_name_s[i] == "use") | |
629 | att_name_e[i] = a_use; | |
630 | else if (att_name_s[i] == "value") | |
631 | att_name_e[i] = a_value; | |
3abe9331 | 632 | else if (att_name_s[i] == "version") { |
633 | } | |
970ed795 EL |
634 | } |
635 | actualTagAttributes.fillUp(att_name_e, att_value_s, att_count); | |
636 | delete [] att_name_s; | |
637 | delete [] att_value_s; | |
638 | delete [] att_name_e; | |
639 | } | |
640 | ||
641 | XMLParser::TagAttributes::TagAttributes(XMLParser * withThisParser) | |
642 | : parser(withThisParser) | |
3abe9331 | 643 | , attributeFormDefault(notset) |
644 | , base() | |
645 | , default_() | |
646 | , elementFormDefault(notset) | |
647 | , fixed() | |
648 | , form(notset) | |
649 | , id() | |
650 | , itemType() | |
651 | , maxOccurs(1) | |
652 | , memberTypes() | |
653 | , minOccurs(1) | |
654 | , mixed(false) | |
655 | , name() | |
656 | , namespace_() | |
657 | , nillable(false) | |
658 | , ref() | |
659 | , schemaLocation() | |
660 | , source() | |
661 | , targetNamespace() | |
662 | , type() | |
663 | , use(optional) | |
664 | , value() { | |
665 | } | |
666 | ||
667 | void XMLParser::TagAttributes::fillUp(TagAttributeName * att_name_e, Mstring * att_value_s, const int att_count) { | |
970ed795 EL |
668 | /** |
669 | * Reset | |
670 | */ | |
3abe9331 | 671 | abstract = false; |
970ed795 EL |
672 | attributeFormDefault = notset; |
673 | base.clear(); | |
3abe9331 | 674 | block = not_set, |
675 | blockDefault = not_set, | |
970ed795 EL |
676 | default_.clear(); |
677 | elementFormDefault = notset; | |
678 | fixed.clear(); | |
679 | form = notset; | |
680 | id.clear(); | |
681 | itemType.clear(); | |
682 | maxOccurs = 1; | |
683 | memberTypes.clear(); | |
684 | minOccurs = 1; | |
685 | mixed = false; | |
686 | name.clear(); | |
687 | namespace_.clear(); | |
688 | nillable = false; | |
689 | ref.clear(); | |
690 | schemaLocation.clear(); | |
691 | source.clear(); | |
3abe9331 | 692 | substitionGroup = empty_string; |
970ed795 EL |
693 | targetNamespace.clear(); |
694 | type.clear(); | |
695 | use = optional; | |
696 | value.clear(); | |
697 | /** | |
698 | * Upload | |
699 | */ | |
700 | for (int i = 0; i != att_count; ++i) { | |
3abe9331 | 701 | switch (att_name_e[i]) { |
702 | case a_abstract: // Not supported by now | |
703 | if (att_value_s[i] == "true") { | |
704 | abstract = true; | |
705 | } else if (att_value_s[i] == "false") { | |
706 | abstract = false; | |
707 | } | |
708 | case a_attributeFormDefault: // qualified | unqualified | |
709 | if (att_value_s[i] == "qualified") { | |
710 | attributeFormDefault = qualified; | |
711 | } else if (att_value_s[i] == "unqualified") { | |
712 | attributeFormDefault = unqualified; | |
713 | } | |
714 | break; | |
715 | case a_base: // QName = anyURI + NCName | |
716 | base = att_value_s[i]; | |
717 | break; | |
718 | case a_block: // Not supported by now | |
719 | if(att_value_s[i] == "#all"){ | |
720 | block = all; | |
721 | }else if(att_value_s[i] == "substitution"){ | |
722 | block = substitution; | |
723 | }else if(att_value_s[i] == "restriction"){ | |
724 | block = restriction; | |
725 | }else if(att_value_s[i] == "extension"){ | |
726 | block = extension; | |
727 | } | |
728 | break; | |
729 | case a_blockDefault: // Not supported by now | |
730 | if(att_value_s[i] == "#all"){ | |
731 | blockDefault = all; | |
732 | }else if(att_value_s[i] == "substitution"){ | |
733 | blockDefault = substitution; | |
734 | }else if(att_value_s[i] == "restriction"){ | |
735 | blockDefault = restriction; | |
736 | }else if(att_value_s[i] == "extension"){ | |
737 | blockDefault = extension; | |
738 | } | |
739 | break; | |
740 | case a_default: // string | |
741 | default_ = att_value_s[i]; | |
742 | break; | |
743 | case a_elementFormDefault: | |
744 | if (att_value_s[i] == "qualified") { | |
745 | elementFormDefault = qualified; | |
746 | } else if (att_value_s[i] == "unqualified") { | |
747 | elementFormDefault = unqualified; | |
748 | } | |
749 | break; | |
750 | case a_final: // Not supported by now | |
751 | break; | |
752 | case a_finalDefault: // Not supported by now | |
753 | break; | |
754 | case a_fixed: // string | |
755 | fixed = att_value_s[i]; | |
756 | break; | |
757 | case a_form: // qualified | unqualified | |
758 | if (att_value_s[i] == "qualified") { | |
759 | form = qualified; | |
760 | } else if (att_value_s[i] == "unqualified") { | |
761 | form = unqualified; | |
762 | } | |
763 | break; | |
764 | case a_lang: | |
765 | break; | |
766 | case a_id: // ID = NCName | |
767 | id = att_value_s[i]; | |
768 | break; | |
769 | case a_itemType: // QName = anyURI + NCName /- used in 'list' tag only | |
770 | itemType = att_value_s[i]; | |
771 | break; | |
772 | case a_maxOccurs: // nonNegativeinteger or 'unbounded' | |
773 | if (att_value_s[i] == "unbounded") { | |
774 | maxOccurs = ULLONG_MAX; | |
775 | } else { | |
776 | maxOccurs = strtoull(att_value_s[i].c_str(), NULL, 0); | |
777 | } | |
778 | break; | |
779 | case a_memberTypes: // list of QNames - used in 'union' tag only | |
780 | memberTypes = att_value_s[i]; | |
781 | break; | |
782 | case a_minOccurs: // nonNegativeInteger | |
783 | minOccurs = strtoull(att_value_s[i].c_str(), NULL, 0); | |
784 | break; | |
785 | case a_mixed: // true | false | |
786 | if (att_value_s[i] == "true") { | |
787 | mixed = true; | |
788 | } else if (att_value_s[i] == "false") { | |
789 | mixed = false; | |
790 | } | |
791 | break; | |
792 | case a_name: // NCName | |
793 | name = att_value_s[i]; | |
794 | break; | |
795 | case a_namespace: // anyURI | |
796 | namespace_ = att_value_s[i]; | |
797 | break; | |
798 | case a_nillable: // true | false | |
799 | if (att_value_s[i] == "true") { | |
800 | nillable = true; | |
801 | } else if (att_value_s[i] == "false") { | |
802 | nillable = false; | |
803 | } | |
804 | break; | |
805 | case a_processContents: // Not supported by now | |
806 | break; | |
807 | case a_ref: // QName = anyURI + NCName | |
808 | ref = att_value_s[i]; | |
809 | break; | |
810 | case a_schemaLocation: // anyURI | |
811 | schemaLocation = att_value_s[i]; | |
812 | break; | |
813 | case a_substitutionGroup: | |
814 | substitionGroup = att_value_s[i]; | |
815 | break; | |
816 | case a_targetNamespace: // anyURI | |
817 | targetNamespace = att_value_s[i]; | |
818 | break; | |
819 | case a_type: // QName = anyURI + NCName | |
820 | type = att_value_s[i]; | |
821 | break; | |
822 | case a_use: // optional | prohibited | required - used in 'use' tag only | |
823 | if (att_value_s[i] == "optional") { | |
824 | use = optional; | |
825 | } else if (att_value_s[i] == "prohibited") { | |
826 | use = prohibited; | |
827 | } else if (att_value_s[i] == "required") { | |
828 | use = required; | |
829 | } | |
830 | break; | |
831 | case a_value: // value of FACETS | |
832 | value = att_value_s[i]; | |
833 | break; | |
834 | case a_source: | |
835 | case a_xpath: | |
836 | case a_version: // Not supported by now | |
837 | break; | |
838 | case a_NOTSET: | |
839 | break; | |
840 | default: | |
841 | fprintf(stderr, "Unknown TagAttributeName %d\n", att_name_e[i]); | |
842 | abort(); | |
843 | break; | |
970ed795 EL |
844 | } |
845 | } | |
846 | } | |
2b00ec8e | 847 |