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