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