|
1 /* |
|
2 * libxml2_sax2.c : Default SAX2 handler to build a tree. |
|
3 * |
|
4 * See Copyright for the status of this software. |
|
5 * |
|
6 * Daniel Veillard <daniel@veillard.com> |
|
7 * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
8 */ |
|
9 |
|
10 #define IN_LIBXML |
|
11 |
|
12 #include "xmlenglibxml.h" |
|
13 |
|
14 #include <stdlib.h> |
|
15 #include <string.h> |
|
16 #include <stdapis/libxml2/libxml2_parserinternals.h> |
|
17 #include "libxml2_xmlerror2.h" |
|
18 |
|
19 #ifdef LIBXML_DEBUG_ENABLED |
|
20 #include "libxml2_debugxml.h" |
|
21 #endif |
|
22 |
|
23 #include <stdapis/libxml2/libxml2_uri.h> |
|
24 #include <stdapis/libxml2/libxml2_globals.h> |
|
25 |
|
26 #ifdef LIBXML_HTML_ENABLED |
|
27 #include "libxml2_htmltree.h" |
|
28 #endif |
|
29 |
|
30 /* #define DEBUG_SAX2 */ |
|
31 /* #define DEBUG_SAX2_TREE */ |
|
32 |
|
33 /** |
|
34 * |
|
35 * |
|
36 * macro to flag unimplemented blocks |
|
37 * XML_CATALOG_PREFER user env to select between system/public prefered |
|
38 * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk> |
|
39 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with |
|
40 *> values "system" and "public". I have made the default be "system" to |
|
41 *> match yours. |
|
42 */ |
|
43 #define _TODO_ \ |
|
44 xmlGenericError(xmlGenericErrorContext, \ |
|
45 EMBED_ERRTXT("Unimplemented block at %s:%d\n"), \ |
|
46 __FILE__, __LINE__); |
|
47 |
|
48 /** |
|
49 * xmlValidError: |
|
50 * @param ctxt an XML validation parser context |
|
51 * @param error the error number |
|
52 * @param msg the error message |
|
53 * @param str1 extra data |
|
54 * @param str2 extra data |
|
55 * |
|
56 * Handle a validation error |
|
57 */ |
|
58 static void |
|
59 xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error, |
|
60 const char *msg, const char *str1, const char *str2) |
|
61 { |
|
62 xmlStructuredErrorFunc schannel = NULL; |
|
63 |
|
64 if ((ctxt != NULL) && (ctxt->disableSAX != 0) && |
|
65 (ctxt->instate == XML_PARSER_EOF)) |
|
66 return; |
|
67 ctxt->errNo = error; |
|
68 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC)) |
|
69 schannel = ctxt->sax->serror; |
|
70 __xmlRaiseError(schannel, |
|
71 ctxt->vctxt.error, ctxt->vctxt.userData, |
|
72 ctxt, NULL, XML_FROM_DTD, error, |
|
73 XML_ERR_ERROR, NULL, 0, (const char *) str1, |
|
74 (const char *) str2, NULL, 0, 0, |
|
75 msg, (const char *) str1, (const char *) str2); |
|
76 ctxt->valid = 0; |
|
77 } |
|
78 |
|
79 /** |
|
80 * xmlSAX2GetPublicId: |
|
81 * @param ctx the user data (XML parser context) |
|
82 * |
|
83 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN" |
|
84 * |
|
85 * Returns a xmlChar * |
|
86 */ |
|
87 XMLPUBFUNEXPORT const xmlChar * |
|
88 xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED) |
|
89 { |
|
90 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ |
|
91 if(ctx) |
|
92 return NULL; // just to use ctx |
|
93 return(NULL); |
|
94 } |
|
95 |
|
96 /** |
|
97 * xmlSAX2GetSystemId: |
|
98 * @param ctx the user data (XML parser context) |
|
99 * |
|
100 * Provides the system ID, basically URL or filename e.g. |
|
101 * http://www.sgmlsource.com/dtds/memo.dtd |
|
102 * |
|
103 * Returns a xmlChar * |
|
104 */ |
|
105 XMLPUBFUNEXPORT const xmlChar * |
|
106 xmlSAX2GetSystemId(void *ctx) |
|
107 { |
|
108 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
109 return((const xmlChar *) ctxt->input->filename); |
|
110 } |
|
111 |
|
112 /** |
|
113 * xmlSAX2GetLineNumber: |
|
114 * @param ctx the user data (XML parser context) |
|
115 * |
|
116 * Provide the line number of the current parsing point. |
|
117 * |
|
118 * Returns an int |
|
119 */ |
|
120 XMLPUBFUNEXPORT int |
|
121 xmlSAX2GetLineNumber(void *ctx) |
|
122 { |
|
123 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
124 return(ctxt->input->line); |
|
125 } |
|
126 |
|
127 /** |
|
128 * xmlSAX2GetColumnNumber: |
|
129 * @param ctx the user data (XML parser context) |
|
130 * |
|
131 * Provide the column number of the current parsing point. |
|
132 * |
|
133 * Returns an int |
|
134 */ |
|
135 XMLPUBFUNEXPORT int |
|
136 xmlSAX2GetColumnNumber(void *ctx) |
|
137 { |
|
138 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
139 return(ctxt->input->col); |
|
140 } |
|
141 |
|
142 /** |
|
143 * xmlSAX2IsStandalone: |
|
144 * @param ctx the user data (XML parser context) |
|
145 * |
|
146 * Is this document tagged standalone ? |
|
147 * |
|
148 * Returns 1 if true |
|
149 */ |
|
150 XMLPUBFUNEXPORT int |
|
151 xmlSAX2IsStandalone(void *ctx) |
|
152 { |
|
153 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
154 return(ctxt->myDoc->standalone == 1); |
|
155 } |
|
156 |
|
157 /** |
|
158 * xmlSAX2HasInternalSubset: |
|
159 * @param ctx the user data (XML parser context) |
|
160 * |
|
161 * Does this document has an internal subset |
|
162 * |
|
163 * Returns 1 if true |
|
164 */ |
|
165 XMLPUBFUNEXPORT int |
|
166 xmlSAX2HasInternalSubset(void *ctx) |
|
167 { |
|
168 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
169 return(ctxt->myDoc->intSubset != NULL); |
|
170 } |
|
171 |
|
172 /** |
|
173 * xmlSAX2HasExternalSubset: |
|
174 * @param ctx the user data (XML parser context) |
|
175 * |
|
176 * Does this document has an external subset |
|
177 * |
|
178 * Returns 1 if true |
|
179 */ |
|
180 XMLPUBFUNEXPORT int |
|
181 xmlSAX2HasExternalSubset(void *ctx) |
|
182 { |
|
183 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
184 return(ctxt->myDoc->extSubset != NULL); |
|
185 } |
|
186 |
|
187 /** |
|
188 * xmlSAX2InternalSubset: |
|
189 * @param ctx the user data (XML parser context) |
|
190 * @param name the root element name |
|
191 * @param ExternalID the external ID |
|
192 * @param SystemID the SYSTEM ID (e.g. filename or URL) |
|
193 * |
|
194 * Callback on internal subset declaration. |
|
195 */ |
|
196 XMLPUBFUNEXPORT void |
|
197 xmlSAX2InternalSubset(void *ctx, const xmlChar *name, |
|
198 const xmlChar *ExternalID, const xmlChar *SystemID) |
|
199 { |
|
200 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
201 xmlDtdPtr dtd; |
|
202 #ifdef DEBUG_SAX |
|
203 xmlGenericError(xmlGenericErrorContext, |
|
204 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n", |
|
205 name, ExternalID, SystemID); |
|
206 #endif |
|
207 |
|
208 if (ctxt->myDoc == NULL) |
|
209 return; |
|
210 dtd = xmlGetIntSubset(ctxt->myDoc); |
|
211 if (dtd != NULL) { |
|
212 if (ctxt->html) |
|
213 return; |
|
214 xmlUnlinkNode((xmlNodePtr) dtd); |
|
215 xmlFreeDtd(dtd); |
|
216 ctxt->myDoc->intSubset = NULL; |
|
217 } |
|
218 ctxt->myDoc->intSubset = xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID); |
|
219 } |
|
220 |
|
221 /** |
|
222 * xmlSAX2ExternalSubset: |
|
223 * @param ctx the user data (XML parser context) |
|
224 * @param name the root element name |
|
225 * @param ExternalID the external ID |
|
226 * @param SystemID the SYSTEM ID (e.g. filename or URL) |
|
227 * |
|
228 * Callback on external subset declaration. |
|
229 */ |
|
230 XMLPUBFUNEXPORT void |
|
231 xmlSAX2ExternalSubset(void *ctx, const xmlChar *name, |
|
232 const xmlChar *ExternalID, const xmlChar *SystemID) |
|
233 { |
|
234 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
235 #ifdef DEBUG_SAX |
|
236 xmlGenericError(xmlGenericErrorContext, |
|
237 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n", |
|
238 name, ExternalID, SystemID); |
|
239 #endif |
|
240 if (((ExternalID != NULL) || (SystemID != NULL)) && |
|
241 (((ctxt->validate) || (ctxt->loadsubset != 0)) && |
|
242 (ctxt->wellFormed && ctxt->myDoc))) { |
|
243 /* |
|
244 * Try to fetch and parse the external subset. |
|
245 */ |
|
246 xmlParserInputPtr oldinput; |
|
247 int oldinputNr; |
|
248 int oldinputMax; |
|
249 xmlParserInputPtr *oldinputTab; |
|
250 xmlParserInputPtr input = NULL; |
|
251 xmlCharEncoding enc; |
|
252 int oldcharset; |
|
253 |
|
254 /* |
|
255 * Ask the Entity resolver to load the damn thing |
|
256 */ |
|
257 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL)) |
|
258 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, |
|
259 SystemID); |
|
260 if (input == NULL) { |
|
261 return; |
|
262 } |
|
263 |
|
264 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID); |
|
265 |
|
266 /* |
|
267 * make sure we won't destroy the main document context |
|
268 */ |
|
269 |
|
270 oldinput = ctxt->input; |
|
271 oldinputNr = ctxt->inputNr; |
|
272 oldinputMax = ctxt->inputMax; |
|
273 oldinputTab = ctxt->inputTab; |
|
274 oldcharset = ctxt->charset; |
|
275 |
|
276 ctxt->inputTab = (xmlParserInputPtr *) |
|
277 xmlMalloc(5 * sizeof(xmlParserInputPtr)); |
|
278 if (ctxt->inputTab == NULL) { |
|
279 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
280 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
281 ctxt->sax->error(ctxt->userData, |
|
282 EMBED_ERRTXT("xmlSAX2ExternalSubset: out of memory\n")); |
|
283 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
284 ctxt->instate = XML_PARSER_EOF; |
|
285 ctxt->disableSAX = 1; |
|
286 ctxt->input = oldinput; |
|
287 ctxt->inputNr = oldinputNr; |
|
288 ctxt->inputMax = oldinputMax; |
|
289 ctxt->inputTab = oldinputTab; |
|
290 ctxt->charset = oldcharset; |
|
291 return; |
|
292 } |
|
293 ctxt->inputNr = 0; |
|
294 ctxt->inputMax = 5; |
|
295 ctxt->input = NULL; |
|
296 xmlPushInput(ctxt, input); |
|
297 |
|
298 /* |
|
299 * On the fly encoding conversion if needed |
|
300 */ |
|
301 if (ctxt->input->length >= 4) { |
|
302 enc = xmlDetectCharEncoding(ctxt->input->cur, 4); |
|
303 xmlSwitchEncoding(ctxt, enc); |
|
304 } |
|
305 |
|
306 if (input->filename == NULL) |
|
307 input->filename = (char *) xmlCanonicPath(SystemID); |
|
308 input->line = 1; |
|
309 input->col = 1; |
|
310 input->base = ctxt->input->cur; |
|
311 input->cur = ctxt->input->cur; |
|
312 input->free = NULL; |
|
313 |
|
314 /* |
|
315 * let's parse that entity knowing it's an external subset. |
|
316 */ |
|
317 xmlParseExternalSubset(ctxt, ExternalID, SystemID); |
|
318 |
|
319 /* |
|
320 * Free up the external entities |
|
321 */ |
|
322 |
|
323 while (ctxt->inputNr > 1) |
|
324 xmlPopInput(ctxt); |
|
325 xmlFreeInputStream(ctxt->input); |
|
326 xmlFree(ctxt->inputTab); |
|
327 |
|
328 /* |
|
329 * Restore the parsing context of the main entity |
|
330 */ |
|
331 ctxt->input = oldinput; |
|
332 ctxt->inputNr = oldinputNr; |
|
333 ctxt->inputMax = oldinputMax; |
|
334 ctxt->inputTab = oldinputTab; |
|
335 ctxt->charset = oldcharset; |
|
336 /* ctxt->wellFormed = oldwellFormed; */ |
|
337 } |
|
338 } |
|
339 |
|
340 /** |
|
341 * xmlSAX2ResolveEntity: |
|
342 * @param ctx the user data (XML parser context) |
|
343 * @param publicId The public ID of the entity |
|
344 * @param systemId The system ID of the entity |
|
345 * |
|
346 * The entity loader, to control the loading of external entities, |
|
347 * the application can either: |
|
348 * - override this xmlSAX2ResolveEntity() callback in the SAX block |
|
349 * - or better use the xmlSetExternalEntityLoader() function to |
|
350 * set up it's own entity resolution routine |
|
351 * |
|
352 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. |
|
353 */ |
|
354 XMLPUBFUNEXPORT xmlParserInputPtr |
|
355 xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId) |
|
356 { |
|
357 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
358 xmlParserInputPtr ret; |
|
359 xmlChar* URI; |
|
360 const char* base = NULL; |
|
361 |
|
362 if (ctxt->input) |
|
363 base = ctxt->input->filename; |
|
364 if (!base) |
|
365 base = ctxt->directory; |
|
366 |
|
367 URI = xmlBuildURI(systemId, (const xmlChar *) base); |
|
368 |
|
369 #ifdef DEBUG_SAX |
|
370 xmlGenericError(xmlGenericErrorContext, |
|
371 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId); |
|
372 #endif |
|
373 |
|
374 ret = xmlLoadExternalEntity((const char *) URI, |
|
375 (const char *) publicId, ctxt); |
|
376 if (URI) |
|
377 xmlFree(URI); |
|
378 return(ret); |
|
379 } |
|
380 |
|
381 /** |
|
382 * xmlSAX2GetEntity: |
|
383 * @param ctx the user data (XML parser context) |
|
384 * @param name The entity name |
|
385 * |
|
386 * Get an entity by name |
|
387 * |
|
388 * Returns the xmlEntityPtr if found. |
|
389 */ |
|
390 XMLPUBFUNEXPORT xmlEntityPtr |
|
391 xmlSAX2GetEntity(void *ctx, const xmlChar *name) |
|
392 { |
|
393 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
394 xmlEntityPtr ret = NULL; |
|
395 |
|
396 #ifdef DEBUG_SAX |
|
397 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2GetEntity(%s)\n", name); |
|
398 #endif |
|
399 |
|
400 if (ctxt->inSubset == 0) { |
|
401 ret = xmlGetPredefinedEntity(name); |
|
402 if (ret != NULL) |
|
403 return(ret); |
|
404 } |
|
405 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) |
|
406 { |
|
407 if (ctxt->inSubset == 2) { |
|
408 ctxt->myDoc->standalone = 0; |
|
409 ret = xmlGetDocEntity(ctxt->myDoc, name); |
|
410 ctxt->myDoc->standalone = 1; |
|
411 } else { |
|
412 ret = xmlGetDocEntity(ctxt->myDoc, name); |
|
413 if (ret == NULL) { |
|
414 ctxt->myDoc->standalone = 0; |
|
415 ret = xmlGetDocEntity(ctxt->myDoc, name); |
|
416 if (ret != NULL) { |
|
417 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
418 ctxt->sax->error(ctxt->userData, |
|
419 EMBED_ERRTXT("Entity(%s) document marked standalone but requires external subset\n"), |
|
420 name); |
|
421 ctxt->valid = 0; |
|
422 ctxt->wellFormed = 0; |
|
423 } |
|
424 ctxt->myDoc->standalone = 1; |
|
425 } |
|
426 } |
|
427 } else { |
|
428 ret = xmlGetDocEntity(ctxt->myDoc, name); |
|
429 } |
|
430 if (ret && |
|
431 ((ctxt->validate) || (ctxt->replaceEntities)) && |
|
432 !ret->children && |
|
433 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) |
|
434 { |
|
435 int val; |
|
436 |
|
437 /* |
|
438 * for validation purposes we really need to fetch and |
|
439 * parse the external entity |
|
440 */ |
|
441 xmlNodePtr children; |
|
442 |
|
443 val = xmlParseCtxtExternalEntity(ctxt, ret->URI, ret->ExternalID, &children); |
|
444 |
|
445 if (val == 0) { |
|
446 xmlAddChildList((xmlNodePtr) ret, children); |
|
447 } else { |
|
448 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
449 ctxt->sax->error(ctxt->userData, |
|
450 EMBED_ERRTXT("Failure to process entity %s\n"), name); |
|
451 ctxt->wellFormed = 0; |
|
452 ctxt->valid = 0; |
|
453 ctxt->validate = 0; |
|
454 return(NULL); |
|
455 } |
|
456 ret->owner = 1; |
|
457 } |
|
458 return(ret); |
|
459 } |
|
460 |
|
461 /** |
|
462 * xmlSAX2GetParameterEntity: |
|
463 * @param ctx the user data (XML parser context) |
|
464 * @param name The entity name |
|
465 * |
|
466 * Get a parameter entity by name |
|
467 * |
|
468 * Returns the xmlEntityPtr if found. |
|
469 */ |
|
470 XMLPUBFUNEXPORT xmlEntityPtr |
|
471 xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name) |
|
472 { |
|
473 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
474 xmlEntityPtr ret; |
|
475 |
|
476 #ifdef DEBUG_SAX |
|
477 xmlGenericError(xmlGenericErrorContext, |
|
478 "SAX.xmlSAX2GetParameterEntity(%s)\n", name); |
|
479 #endif |
|
480 |
|
481 ret = xmlGetParameterEntity(ctxt->myDoc, name); |
|
482 return(ret); |
|
483 } |
|
484 |
|
485 |
|
486 /** |
|
487 * xmlSAX2EntityDecl: |
|
488 * @param ctx the user data (XML parser context) |
|
489 * @param name the entity name |
|
490 * @param type the entity type |
|
491 * @param publicId The public ID of the entity |
|
492 * @param systemId The system ID of the entity |
|
493 * @param content the entity value (without processing). |
|
494 * |
|
495 * An entity definition has been parsed |
|
496 */ |
|
497 XMLPUBFUNEXPORT void |
|
498 xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type, |
|
499 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) |
|
500 { |
|
501 xmlEntityPtr ent; |
|
502 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
503 |
|
504 #ifdef DEBUG_SAX |
|
505 xmlGenericError(xmlGenericErrorContext, |
|
506 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n", |
|
507 name, type, publicId, systemId, content); |
|
508 #endif |
|
509 if (ctxt->inSubset == 1) |
|
510 { |
|
511 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId, |
|
512 systemId, content); |
|
513 if (!ent && |
|
514 ctxt->pedantic && |
|
515 ctxt->sax && ctxt->sax->warning) |
|
516 { |
|
517 ctxt->sax->warning(ctxt->userData, |
|
518 EMBED_ERRTXT("Entity(%s) already defined in the internal subset\n"), name); |
|
519 } |
|
520 if (ent && !ent->URI && systemId) |
|
521 { |
|
522 xmlChar *URI; |
|
523 const char *base = NULL; |
|
524 |
|
525 if (ctxt->input) |
|
526 base = ctxt->input->filename; |
|
527 if (!base) |
|
528 base = ctxt->directory; |
|
529 |
|
530 URI = xmlBuildURI(systemId, (const xmlChar *) base); |
|
531 ent->URI = URI; |
|
532 } |
|
533 } |
|
534 else if (ctxt->inSubset == 2) |
|
535 { |
|
536 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId, |
|
537 systemId, content); |
|
538 if (!ent && |
|
539 ctxt->pedantic && |
|
540 ctxt->sax && |
|
541 ctxt->sax->warning) |
|
542 { |
|
543 ctxt->sax->warning(ctxt->userData, |
|
544 EMBED_ERRTXT("Entity(%s) already defined in the external subset\n"), name); |
|
545 } |
|
546 if (ent && !ent->URI && systemId) |
|
547 { |
|
548 xmlChar *URI; |
|
549 const char* base = NULL; |
|
550 |
|
551 if (ctxt->input != NULL) |
|
552 base = ctxt->input->filename; |
|
553 if (!base) |
|
554 base = ctxt->directory; |
|
555 |
|
556 URI = xmlBuildURI(systemId, (const xmlChar*) base); |
|
557 ent->URI = URI; |
|
558 } |
|
559 } |
|
560 else if (ctxt->sax && ctxt->sax->error) |
|
561 { |
|
562 ctxt->sax->error(ctxt->userData, |
|
563 EMBED_ERRTXT("SAX.xmlSAX2EntityDecl(%s) called while not in subset\n"), |
|
564 name); |
|
565 } |
|
566 } |
|
567 |
|
568 /** |
|
569 * xmlSAX2AttributeDecl: |
|
570 * @param ctx the user data (XML parser context) |
|
571 * @param elem the name of the element |
|
572 * @param fullname the attribute name |
|
573 * @param type the attribute type |
|
574 * @param def the type of default value |
|
575 * @param defaultValue the attribute default value |
|
576 * @param tree the tree of enumerated value set |
|
577 * |
|
578 * An attribute definition has been parsed |
|
579 */ |
|
580 XMLPUBFUNEXPORT void |
|
581 xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname, |
|
582 int type, int def, const xmlChar *defaultValue, |
|
583 xmlEnumerationPtr tree) |
|
584 { |
|
585 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
586 #ifdef LIBXML_VALID_ENABLED |
|
587 xmlAttributePtr attr; |
|
588 #endif |
|
589 xmlChar *name = NULL, *prefix = NULL; |
|
590 |
|
591 #ifdef DEBUG_SAX |
|
592 xmlGenericError(xmlGenericErrorContext, |
|
593 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n", |
|
594 elem, fullname, type, def, defaultValue); |
|
595 #endif |
|
596 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) && |
|
597 (type != XML_ATTRIBUTE_ID)) { |
|
598 /* |
|
599 * Raise the error but keep the validity flag |
|
600 */ |
|
601 int tmp = ctxt->valid; |
|
602 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE, |
|
603 EMBED_ERRTXT("xml:id : attribute type should be ID\n"), NULL, NULL); |
|
604 ctxt->valid = tmp; |
|
605 } |
|
606 |
|
607 name = xmlSplitQName(ctxt, fullname, &prefix); |
|
608 ctxt->vctxt.valid = 1; |
|
609 if (ctxt->inSubset == 1) |
|
610 { |
|
611 #ifdef LIBXML_VALID_ENABLED |
|
612 attr = |
|
613 #endif |
|
614 xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem, |
|
615 name, prefix, (xmlAttributeType) type, |
|
616 (xmlAttributeDefault) def, defaultValue, tree); |
|
617 } |
|
618 else if (ctxt->inSubset == 2) |
|
619 { |
|
620 #ifdef LIBXML_VALID_ENABLED |
|
621 attr = |
|
622 #endif |
|
623 xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem, |
|
624 name, prefix, (xmlAttributeType) type, |
|
625 (xmlAttributeDefault) def, defaultValue, tree); |
|
626 } |
|
627 else |
|
628 { |
|
629 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
630 ctxt->sax->error(ctxt->userData, |
|
631 EMBED_ERRTXT("SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n"), name); |
|
632 xmlFreeEnumeration(tree); |
|
633 return; |
|
634 } |
|
635 #ifdef LIBXML_VALID_ENABLED |
|
636 if (ctxt->vctxt.valid == 0) |
|
637 ctxt->valid = 0; |
|
638 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) && |
|
639 (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL)) |
|
640 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc, |
|
641 attr); |
|
642 #endif /* LIBXML_VALID_ENABLED */ |
|
643 if (prefix != NULL) |
|
644 xmlFree(prefix); |
|
645 if (name != NULL) |
|
646 xmlFree(name); |
|
647 } |
|
648 |
|
649 /** |
|
650 * xmlSAX2ElementDecl: |
|
651 * @param ctx the user data (XML parser context) |
|
652 * @param name the element name |
|
653 * @param type the element type |
|
654 * @param content the element value tree |
|
655 * |
|
656 * An element definition has been parsed |
|
657 */ |
|
658 XMLPUBFUNEXPORT void |
|
659 xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type, |
|
660 xmlElementContentPtr content) |
|
661 { |
|
662 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
663 #ifdef LIBXML_VALID_ENABLED |
|
664 xmlElementPtr elem = NULL; |
|
665 #endif |
|
666 |
|
667 #ifdef DEBUG_SAX |
|
668 xmlGenericError(xmlGenericErrorContext, |
|
669 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type); |
|
670 #endif |
|
671 |
|
672 if (ctxt->inSubset == 1){ |
|
673 #ifdef LIBXML_VALID_ENABLED |
|
674 elem = |
|
675 #endif |
|
676 xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, |
|
677 name, (xmlElementTypeVal) type, content); |
|
678 } |
|
679 else if (ctxt->inSubset == 2) |
|
680 { |
|
681 #ifdef LIBXML_VALID_ENABLED |
|
682 elem = |
|
683 #endif |
|
684 xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, |
|
685 name, (xmlElementTypeVal) type, content); |
|
686 } |
|
687 else |
|
688 { |
|
689 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
690 ctxt->sax->error(ctxt->userData, |
|
691 EMBED_ERRTXT("SAX.xmlSAX2ElementDecl(%s) called while not in subset\n"), |
|
692 name); |
|
693 return; |
|
694 } |
|
695 #ifdef LIBXML_VALID_ENABLED |
|
696 if (elem == NULL) |
|
697 ctxt->valid = 0; |
|
698 if (ctxt->validate && ctxt->wellFormed && |
|
699 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
700 ctxt->valid &= |
|
701 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem); |
|
702 #endif /* LIBXML_VALID_ENABLED */ |
|
703 } |
|
704 |
|
705 /** |
|
706 * xmlSAX2NotationDecl: |
|
707 * @param ctx the user data (XML parser context) |
|
708 * @param name The name of the notation |
|
709 * @param publicId The public ID of the entity |
|
710 * @param systemId The system ID of the entity |
|
711 * |
|
712 * What to do when a notation declaration has been parsed. |
|
713 */ |
|
714 XMLPUBFUNEXPORT void |
|
715 xmlSAX2NotationDecl(void *ctx, const xmlChar *name, |
|
716 const xmlChar *publicId, const xmlChar *systemId) |
|
717 { |
|
718 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
719 #ifdef LIBXML_VALID_ENABLED |
|
720 xmlNotationPtr nota = NULL; |
|
721 #endif |
|
722 |
|
723 #ifdef DEBUG_SAX |
|
724 xmlGenericError(xmlGenericErrorContext, |
|
725 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId); |
|
726 #endif |
|
727 |
|
728 if ((publicId == NULL) && (systemId == NULL)) { |
|
729 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
730 ctxt->sax->error(ctxt->userData, |
|
731 EMBED_ERRTXT("SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n"), name); |
|
732 ctxt->valid = 0; |
|
733 ctxt->wellFormed = 0; |
|
734 return; |
|
735 } |
|
736 else if (ctxt->inSubset == 1) |
|
737 { |
|
738 #ifdef LIBXML_VALID_ENABLED |
|
739 nota = |
|
740 #endif |
|
741 xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name, |
|
742 publicId, systemId); |
|
743 } |
|
744 else if (ctxt->inSubset == 2) |
|
745 { |
|
746 #ifdef LIBXML_VALID_ENABLED |
|
747 nota = |
|
748 #endif |
|
749 xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name, |
|
750 publicId, systemId); |
|
751 } |
|
752 else |
|
753 { |
|
754 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
755 ctxt->sax->error(ctxt->userData, |
|
756 EMBED_ERRTXT("SAX.xmlSAX2NotationDecl(%s) called while not in subset\n"), name); |
|
757 return; |
|
758 } |
|
759 #ifdef LIBXML_VALID_ENABLED |
|
760 if (nota == NULL) |
|
761 ctxt->valid = 0; |
|
762 if (ctxt->validate && ctxt->wellFormed && |
|
763 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
764 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc, |
|
765 nota); |
|
766 #endif /* LIBXML_VALID_ENABLED */ |
|
767 } |
|
768 |
|
769 /** |
|
770 * xmlSAX2UnparsedEntityDecl: |
|
771 * @param ctx the user data (XML parser context) |
|
772 * @param name The name of the entity |
|
773 * @param publicId The public ID of the entity |
|
774 * @param systemId The system ID of the entity |
|
775 * @param notationName the name of the notation |
|
776 * |
|
777 * What to do when an unparsed entity declaration is parsed |
|
778 */ |
|
779 XMLPUBFUNEXPORT void |
|
780 xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name, |
|
781 const xmlChar *publicId, const xmlChar *systemId, |
|
782 const xmlChar *notationName) |
|
783 { |
|
784 xmlEntityPtr ent; |
|
785 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
786 #ifdef DEBUG_SAX |
|
787 xmlGenericError(xmlGenericErrorContext, |
|
788 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n", |
|
789 name, publicId, systemId, notationName); |
|
790 #endif |
|
791 if (ctxt->inSubset == 1) |
|
792 { |
|
793 ent = xmlAddDocEntity(ctxt->myDoc, name, |
|
794 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, |
|
795 publicId, systemId, notationName); |
|
796 if (!ent && ctxt->pedantic && |
|
797 ctxt->sax && ctxt->sax->warning) |
|
798 { |
|
799 ctxt->sax->warning(ctxt->userData, |
|
800 EMBED_ERRTXT("Entity(%s) already defined in the internal subset\n"), name); |
|
801 } |
|
802 if (ent && !ent->URI && systemId) |
|
803 { |
|
804 xmlChar *URI; |
|
805 const char* base = NULL; |
|
806 |
|
807 if (ctxt->input) |
|
808 base = ctxt->input->filename; |
|
809 if (!base) |
|
810 base = ctxt->directory; |
|
811 |
|
812 URI = xmlBuildURI(systemId, (const xmlChar *) base); |
|
813 ent->URI = URI; |
|
814 } |
|
815 } |
|
816 else if (ctxt->inSubset == 2) |
|
817 { |
|
818 ent = xmlAddDtdEntity(ctxt->myDoc, name, |
|
819 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY, |
|
820 publicId, systemId, notationName); |
|
821 if (!ent && ctxt->pedantic && |
|
822 ctxt->sax && ctxt->sax->warning) |
|
823 { |
|
824 ctxt->sax->warning(ctxt->userData, |
|
825 EMBED_ERRTXT("Entity(%s) already defined in the external subset\n"), name); |
|
826 } |
|
827 if (ent && !ent->URI && systemId) |
|
828 { |
|
829 xmlChar *URI; |
|
830 const char* base = NULL; |
|
831 |
|
832 if (ctxt->input) |
|
833 base = ctxt->input->filename; |
|
834 if (!base) |
|
835 base = ctxt->directory; |
|
836 |
|
837 URI = xmlBuildURI(systemId, (const xmlChar*) base); |
|
838 ent->URI = URI; |
|
839 } |
|
840 } |
|
841 else if (ctxt->sax && ctxt->sax->error) |
|
842 { |
|
843 ctxt->sax->error(ctxt->userData, |
|
844 EMBED_ERRTXT("SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n"), name); |
|
845 } |
|
846 } |
|
847 |
|
848 /** |
|
849 * xmlSAX2SetDocumentLocator: |
|
850 * @param ctx the user data (XML parser context) |
|
851 * @param loc A SAX Locator |
|
852 * |
|
853 * Receive the document locator at startup, actually xmlDefaultSAXLocator |
|
854 * Everything is available on the context, so this is useless in our case. |
|
855 */ |
|
856 XMLPUBFUNEXPORT void |
|
857 xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED) |
|
858 { |
|
859 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ |
|
860 #ifdef DEBUG_SAX |
|
861 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2SetDocumentLocator()\n"); |
|
862 #endif |
|
863 if(ctx) return; // just to use ctx |
|
864 } |
|
865 |
|
866 /** |
|
867 * xmlSAX2StartDocument: |
|
868 * @param ctx the user data (XML parser context) |
|
869 * |
|
870 * called when the document start being processed. |
|
871 * |
|
872 * OOM: possible --> check OOM flag |
|
873 */ |
|
874 XMLPUBFUNEXPORT void xmlSAX2StartDocument(void *ctx) |
|
875 { |
|
876 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
877 xmlDocPtr doc = NULL; |
|
878 |
|
879 #ifdef DEBUG_SAX |
|
880 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2StartDocument()\n"); |
|
881 #endif |
|
882 if (ctxt->html) { |
|
883 |
|
884 #ifdef LIBXML_HTML_ENABLED |
|
885 if (ctxt->myDoc == NULL) |
|
886 doc = ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL); |
|
887 if (!ctxt->myDoc) |
|
888 goto OOM; |
|
889 #else |
|
890 xmlGenericError(xmlGenericErrorContext, EMBED_ERRTXT("libxml2 built without HTML support\n")); |
|
891 ctxt->errNo = XML_ERR_INTERNAL_ERROR; |
|
892 goto ERR; |
|
893 #endif |
|
894 } else { // not HTML |
|
895 doc = ctxt->myDoc = xmlNewDoc(ctxt->version); |
|
896 if (!doc) |
|
897 goto OOM; |
|
898 |
|
899 if (ctxt->encoding != NULL){ |
|
900 doc->encoding = xmlStrdup(ctxt->encoding); |
|
901 if(! doc->encoding) |
|
902 goto OOM; |
|
903 } |
|
904 //else |
|
905 // doc->encoding = NULL; // it is NULL after xmlNewDoc |
|
906 doc->standalone = ctxt->standalone; |
|
907 if (ctxt->dictNames && doc) { |
|
908 doc->dict = ctxt->dict; |
|
909 xmlDictReference(doc->dict); |
|
910 } |
|
911 } |
|
912 if ( /* (ctxt->myDoc != NULL) && : it's NOT NULL here */ |
|
913 !doc->URL && |
|
914 ctxt->input && |
|
915 ctxt->input->filename) |
|
916 { |
|
917 doc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename); |
|
918 if (!doc->URL) |
|
919 doc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename); |
|
920 } |
|
921 return; |
|
922 //---------------------------- |
|
923 OOM: |
|
924 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
925 ctxt->sax->error(ctxt->userData, EMBED_ERRTXT("SAX.xmlSAX2StartDocument(): out of memory\n")); |
|
926 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
927 ERR: |
|
928 ctxt->instate = XML_PARSER_EOF; |
|
929 ctxt->disableSAX = 1; |
|
930 return; |
|
931 } |
|
932 |
|
933 /** |
|
934 * xmlSAX2EndDocument: |
|
935 * @param ctx the user data (XML parser context) |
|
936 * |
|
937 * called when the document end has been detected. |
|
938 */ |
|
939 XMLPUBFUNEXPORT void |
|
940 xmlSAX2EndDocument(void *ctx) |
|
941 { |
|
942 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
943 #ifdef DEBUG_SAX |
|
944 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndDocument()\n"); |
|
945 #endif |
|
946 #ifdef LIBXML_VALID_ENABLED |
|
947 if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc && ctxt->myDoc->intSubset) |
|
948 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc); |
|
949 #endif /* LIBXML_VALID_ENABLED */ |
|
950 |
|
951 /* |
|
952 * Grab the encoding if it was added on-the-fly |
|
953 */ |
|
954 if (ctxt->encoding && |
|
955 ctxt->myDoc && |
|
956 !ctxt->myDoc->encoding) |
|
957 { |
|
958 ctxt->myDoc->encoding = ctxt->encoding; |
|
959 ctxt->encoding = NULL; |
|
960 } |
|
961 if (ctxt->inputTab[0]->encoding && |
|
962 ctxt->myDoc && |
|
963 !ctxt->myDoc->encoding) |
|
964 { |
|
965 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding); |
|
966 } |
|
967 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && |
|
968 ctxt->myDoc && |
|
969 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) |
|
970 { |
|
971 ctxt->myDoc->charset = ctxt->charset; |
|
972 } |
|
973 } |
|
974 |
|
975 // Note: old (SAX1) handlers -- name is misleading |
|
976 #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) |
|
977 /** |
|
978 * xmlSAX2AttributeInternal: |
|
979 * @param ctx the user data (XML parser context) |
|
980 * @param fullname The attribute name, including namespace prefix |
|
981 * @param value The attribute value |
|
982 * @param prefix the prefix on the element node |
|
983 * |
|
984 * Handle an attribute that has been read by the parser. |
|
985 * The default handling is to convert the attribute into an |
|
986 * DOM subtree and past it in a new xmlAttr element added to |
|
987 * the element. |
|
988 */ |
|
989 static void |
|
990 xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname, |
|
991 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED) |
|
992 { |
|
993 // DONE: Find and refactor all "namespace" variables to not match C++ keyword |
|
994 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
995 xmlAttrPtr ret; |
|
996 xmlChar *name; |
|
997 xmlChar *ns; |
|
998 xmlChar *nval; |
|
999 xmlNsPtr nameSpace; |
|
1000 |
|
1001 /* |
|
1002 * Split the full name into a namespace prefix and the tag name |
|
1003 */ |
|
1004 name = xmlSplitQName(ctxt, fullname, &ns); |
|
1005 if ((name != NULL) && (name[0] == 0)) { |
|
1006 if (xmlStrEqual(ns, BAD_CAST "xmlns")) { |
|
1007 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
1008 ctxt->sax->error(ctxt->userData, |
|
1009 EMBED_ERRTXT("invalid namespace declaration '%s'\n"), fullname); |
|
1010 } else { |
|
1011 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) |
|
1012 ctxt->sax->warning(ctxt->userData, |
|
1013 EMBED_ERRTXT("Avoid attribute ending with ':' like '%s'\n"), fullname); |
|
1014 } |
|
1015 if (ns != NULL) |
|
1016 xmlFree(ns); |
|
1017 ns = NULL; |
|
1018 xmlFree(name); |
|
1019 name = xmlStrdup(fullname); |
|
1020 } |
|
1021 if (name == NULL) { |
|
1022 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
1023 ctxt->sax->error(ctxt->userData,EMBED_ERRTXT("SAX.xmlSAX2StartElement(): out of memory\n")); |
|
1024 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
1025 ctxt->instate = XML_PARSER_EOF; |
|
1026 ctxt->disableSAX = 1; |
|
1027 if (ns != NULL) |
|
1028 xmlFree(ns); |
|
1029 return; |
|
1030 } |
|
1031 |
|
1032 #ifdef LIBXML_VALID_ENABLED |
|
1033 /* |
|
1034 * Do the last stage of the attribute normalization |
|
1035 * Needed for HTML too: |
|
1036 * http://www.w3.org/TR/html4/types.html#h-6.2 |
|
1037 */ |
|
1038 ctxt->vctxt.valid = 1; |
|
1039 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt, |
|
1040 ctxt->myDoc, ctxt->node, |
|
1041 fullname, value); |
|
1042 if (ctxt->vctxt.valid != 1) { |
|
1043 ctxt->valid = 0; |
|
1044 } |
|
1045 if (nval != NULL) |
|
1046 value = nval; |
|
1047 #else |
|
1048 nval = NULL; |
|
1049 #endif /* LIBXML_VALID_ENABLED */ |
|
1050 |
|
1051 /* |
|
1052 * Check whether it's a namespace definition |
|
1053 */ |
|
1054 if ((!ctxt->html) && (ns == NULL) && |
|
1055 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') && |
|
1056 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) |
|
1057 { |
|
1058 xmlNsPtr nsret; |
|
1059 xmlChar *val; |
|
1060 |
|
1061 if (!ctxt->replaceEntities) { |
|
1062 ctxt->depth++; |
|
1063 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,0,0,0); |
|
1064 ctxt->depth--; |
|
1065 } else { |
|
1066 val = (xmlChar *) value; |
|
1067 } |
|
1068 |
|
1069 if (val[0] != 0) { |
|
1070 xmlURIPtr uri; |
|
1071 |
|
1072 uri = xmlParseURI((const char *)val); |
|
1073 if (uri == NULL) { |
|
1074 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) |
|
1075 ctxt->sax->warning(ctxt->userData, |
|
1076 EMBED_ERRTXT("xmlns: %s not a valid URI\n"), val); |
|
1077 } else { |
|
1078 if (uri->scheme == NULL) { |
|
1079 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) |
|
1080 ctxt->sax->warning(ctxt->userData, |
|
1081 EMBED_ERRTXT("xmlns: URI %s is not absolute\n"), val); |
|
1082 } |
|
1083 xmlFreeURI(uri); |
|
1084 } |
|
1085 } |
|
1086 |
|
1087 /* a default namespace definition */ |
|
1088 nsret = xmlNewNs(ctxt->node, val, NULL); |
|
1089 |
|
1090 #ifdef LIBXML_VALID_ENABLED |
|
1091 /* |
|
1092 * Validate also for namespace decls, they are attributes from |
|
1093 * an XML-1.0 perspective |
|
1094 */ |
|
1095 if (nsret != NULL && |
|
1096 ctxt->validate && |
|
1097 ctxt->wellFormed && |
|
1098 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
1099 { |
|
1100 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, |
|
1101 ctxt->node, prefix, nsret, val); |
|
1102 } |
|
1103 #endif /* LIBXML_VALID_ENABLED */ |
|
1104 if (name != NULL) |
|
1105 xmlFree(name); |
|
1106 if (nval != NULL) |
|
1107 xmlFree(nval); |
|
1108 if (val != value) |
|
1109 xmlFree(val); |
|
1110 return; |
|
1111 } |
|
1112 |
|
1113 if ((!ctxt->html) && |
|
1114 (ns != NULL) && |
|
1115 (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') && |
|
1116 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) |
|
1117 { |
|
1118 xmlNsPtr nsret; |
|
1119 xmlChar *val; |
|
1120 |
|
1121 if (!ctxt->replaceEntities) { |
|
1122 ctxt->depth++; |
|
1123 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF, |
|
1124 0,0,0); |
|
1125 ctxt->depth--; |
|
1126 if (val == NULL) { |
|
1127 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
1128 ctxt->sax->error(ctxt->userData, EMBED_ERRTXT("SAX.xmlSAX2StartElement(): out of memory\n")); |
|
1129 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
1130 ctxt->instate = XML_PARSER_EOF; |
|
1131 ctxt->disableSAX = 1; |
|
1132 xmlFree(ns); |
|
1133 if (name != NULL) |
|
1134 xmlFree(name); |
|
1135 return; |
|
1136 } |
|
1137 } else { |
|
1138 val = (xmlChar *) value; |
|
1139 } |
|
1140 |
|
1141 if (val[0] == 0) { |
|
1142 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
1143 ctxt->sax->error(ctxt->userData, EMBED_ERRTXT("Empty namespace name for prefix %s\n"), name); |
|
1144 } |
|
1145 if ((ctxt->pedantic != 0) && (val[0] != 0)) { |
|
1146 xmlURIPtr uri; |
|
1147 |
|
1148 uri = xmlParseURI((const char *)val); |
|
1149 if (uri == NULL) { |
|
1150 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) |
|
1151 ctxt->sax->warning(ctxt->userData, |
|
1152 EMBED_ERRTXT("xmlns:%s: %s not a valid URI\n"), name, value); |
|
1153 } else { |
|
1154 if (uri->scheme == NULL) { |
|
1155 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) |
|
1156 ctxt->sax->warning(ctxt->userData, |
|
1157 EMBED_ERRTXT("xmlns:%s: URI %s is not absolute\n"), name, value); |
|
1158 } |
|
1159 xmlFreeURI(uri); |
|
1160 } |
|
1161 } |
|
1162 |
|
1163 /* a standard namespace definition */ |
|
1164 nsret = xmlNewNs(ctxt->node, val, name); |
|
1165 xmlFree(ns); |
|
1166 #ifdef LIBXML_VALID_ENABLED |
|
1167 /* |
|
1168 * Validate also for namespace decls, they are attributes from |
|
1169 * an XML-1.0 perspective |
|
1170 */ |
|
1171 if (nsret != NULL && ctxt->validate && ctxt->wellFormed && |
|
1172 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
1173 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, |
|
1174 ctxt->node, prefix, nsret, value); |
|
1175 #endif /* LIBXML_VALID_ENABLED */ |
|
1176 if (name != NULL) |
|
1177 xmlFree(name); |
|
1178 if (nval != NULL) |
|
1179 xmlFree(nval); |
|
1180 if (val != value) |
|
1181 xmlFree(val); |
|
1182 return; |
|
1183 } |
|
1184 |
|
1185 if (ns != NULL) { |
|
1186 xmlAttrPtr prop; |
|
1187 nameSpace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns); |
|
1188 if (nameSpace == NULL) { |
|
1189 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
1190 ctxt->sax->error(ctxt->userData, |
|
1191 EMBED_ERRTXT("Namespace prefix %s of attribute %s is not defined\n"), |
|
1192 ns, name); |
|
1193 } |
|
1194 |
|
1195 prop = ctxt->node->properties; |
|
1196 while (prop != NULL) { |
|
1197 if (prop->ns != NULL) { |
|
1198 if ((xmlStrEqual(name, prop->name)) && |
|
1199 ((nameSpace == prop->ns) || |
|
1200 (xmlStrEqual(nameSpace->href, prop->ns->href)))) { |
|
1201 ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED; |
|
1202 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
1203 ctxt->sax->error(ctxt->userData, |
|
1204 EMBED_ERRTXT("Attribute %s in %s redefined\n"), |
|
1205 name, nameSpace->href); |
|
1206 ctxt->wellFormed = 0; |
|
1207 if (ctxt->recovery == 0) ctxt->disableSAX = 1; |
|
1208 goto error; |
|
1209 } |
|
1210 } |
|
1211 prop = prop->next; |
|
1212 } |
|
1213 } else { |
|
1214 nameSpace = NULL; |
|
1215 } |
|
1216 |
|
1217 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */ |
|
1218 ret = xmlNewNsPropEatName(ctxt->node, nameSpace, name, NULL); |
|
1219 |
|
1220 if (ret != NULL) { |
|
1221 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { |
|
1222 xmlNodePtr tmp; |
|
1223 |
|
1224 ret->children = xmlStringGetNodeList(ctxt->myDoc, value); |
|
1225 tmp = ret->children; |
|
1226 while (tmp != NULL) { |
|
1227 tmp->parent = (xmlNodePtr) ret; |
|
1228 if (tmp->next == NULL) |
|
1229 ret->last = tmp; |
|
1230 tmp = tmp->next; |
|
1231 } |
|
1232 } else if (value != NULL) { |
|
1233 ret->children = xmlNewDocText(ctxt->myDoc, value); |
|
1234 ret->last = ret->children; |
|
1235 if (ret->children != NULL) |
|
1236 ret->children->parent = (xmlNodePtr) ret; |
|
1237 } |
|
1238 } |
|
1239 |
|
1240 #ifdef LIBXML_VALID_ENABLED |
|
1241 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && |
|
1242 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
1243 { |
|
1244 /* |
|
1245 * If we don't substitute entities, the validation should be |
|
1246 * done on a value with replaced entities anyway. |
|
1247 */ |
|
1248 if (!ctxt->replaceEntities) { |
|
1249 xmlChar *val; |
|
1250 |
|
1251 ctxt->depth++; |
|
1252 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,0,0,0); |
|
1253 ctxt->depth--; |
|
1254 |
|
1255 if (val == NULL) |
|
1256 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, ctxt->node, ret, value); |
|
1257 else { |
|
1258 xmlChar *nvalnorm; |
|
1259 |
|
1260 /* |
|
1261 * Do the last stage of the attribute normalization |
|
1262 * It need to be done twice ... it's an extra burden related |
|
1263 * to the ability to keep xmlSAX2References in attributes |
|
1264 */ |
|
1265 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node, fullname, val); |
|
1266 if (nvalnorm != NULL) { |
|
1267 xmlFree(val); |
|
1268 val = nvalnorm; |
|
1269 } |
|
1270 |
|
1271 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, ctxt->node, ret, val); |
|
1272 xmlFree(val); |
|
1273 } |
|
1274 } else { |
|
1275 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc, ctxt->node, ret, value); |
|
1276 } |
|
1277 } else |
|
1278 #endif /* LIBXML_VALID_ENABLED */ |
|
1279 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && |
|
1280 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || |
|
1281 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { |
|
1282 /* |
|
1283 * when validating, the ID registration is done at the attribute |
|
1284 * validation level. Otherwise we have to do specific handling here. |
|
1285 */ |
|
1286 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) |
|
1287 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); |
|
1288 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) |
|
1289 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret); |
|
1290 else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) { |
|
1291 /* |
|
1292 * Add the xml:id value |
|
1293 * |
|
1294 * Open issue: normalization of the value. |
|
1295 */ |
|
1296 if (xmlValidateNCName(value, 1) != 0) { |
|
1297 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, |
|
1298 EMBED_ERRTXT("xml:id : attribute value %s is not an NCName\n"), |
|
1299 (const char *) value, NULL); |
|
1300 } |
|
1301 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret); |
|
1302 } |
|
1303 } |
|
1304 |
|
1305 error: |
|
1306 if (nval != NULL) |
|
1307 xmlFree(nval); |
|
1308 if (ns != NULL) |
|
1309 xmlFree(ns); |
|
1310 } |
|
1311 |
|
1312 /* |
|
1313 * xmlCheckDefaultedAttributes: |
|
1314 * |
|
1315 * Check defaulted attributes from the DTD |
|
1316 */ |
|
1317 static void |
|
1318 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name, |
|
1319 const xmlChar *prefix, const xmlChar **atts) { |
|
1320 xmlElementPtr elemDecl; |
|
1321 const xmlChar *att; |
|
1322 int internal = 1; |
|
1323 int i; |
|
1324 |
|
1325 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix); |
|
1326 if (elemDecl == NULL) { |
|
1327 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix); |
|
1328 internal = 0; |
|
1329 } |
|
1330 |
|
1331 process_external_subset: |
|
1332 |
|
1333 if (elemDecl != NULL) { |
|
1334 xmlAttributePtr attr = elemDecl->attributes; |
|
1335 /* |
|
1336 * Check against defaulted attributes from the external subset |
|
1337 * if the document is stamped as standalone |
|
1338 */ |
|
1339 if ((ctxt->myDoc->standalone == 1) && |
|
1340 (ctxt->myDoc->extSubset != NULL) && |
|
1341 (ctxt->validate)) { |
|
1342 while (attr != NULL) { |
|
1343 if ((attr->defaultValue != NULL) && |
|
1344 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset, |
|
1345 attr->elem, attr->name, |
|
1346 attr->prefix) == attr) && |
|
1347 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, |
|
1348 attr->elem, attr->name, |
|
1349 attr->prefix) == NULL)) { |
|
1350 xmlChar *fulln; |
|
1351 |
|
1352 if (attr->prefix != NULL) { |
|
1353 fulln = xmlStrdup(attr->prefix); |
|
1354 fulln = xmlStrcat(fulln, BAD_CAST ":"); |
|
1355 fulln = xmlStrcat(fulln, attr->name); |
|
1356 } else { |
|
1357 fulln = xmlStrdup(attr->name); |
|
1358 } |
|
1359 |
|
1360 /* |
|
1361 * Check that the attribute is not declared in the |
|
1362 * serialization |
|
1363 */ |
|
1364 att = NULL; |
|
1365 if (atts != NULL) { |
|
1366 i = 0; |
|
1367 att = atts[i]; |
|
1368 while (att != NULL) { |
|
1369 if (xmlStrEqual(att, fulln)) |
|
1370 break; |
|
1371 i += 2; |
|
1372 att = atts[i]; |
|
1373 } |
|
1374 } |
|
1375 if (att == NULL) { |
|
1376 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED, |
|
1377 EMBED_ERRTXT("standalone: attribute %s on %s defaulted from external subset\n"), |
|
1378 (const char *)fulln, |
|
1379 (const char *)attr->elem); |
|
1380 } |
|
1381 } |
|
1382 attr = attr->nexth; |
|
1383 } |
|
1384 } |
|
1385 |
|
1386 /* |
|
1387 * Actually insert defaulted values when needed |
|
1388 */ |
|
1389 attr = elemDecl->attributes; |
|
1390 while (attr != NULL) { |
|
1391 /* |
|
1392 * Make sure that attributes redefinition occuring in the |
|
1393 * internal subset are not overriden by definitions in the |
|
1394 * external subset. |
|
1395 */ |
|
1396 if (attr->defaultValue != NULL) { |
|
1397 /* |
|
1398 * the element should be instantiated in the tree if: |
|
1399 * - this is a namespace prefix |
|
1400 * - the user required for completion in the tree |
|
1401 * like XSLT |
|
1402 * - there isn't already an attribute definition |
|
1403 * in the internal subset overriding it. |
|
1404 */ |
|
1405 if (((attr->prefix != NULL) && |
|
1406 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) || |
|
1407 ((attr->prefix == NULL) && |
|
1408 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) || |
|
1409 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) { |
|
1410 xmlAttributePtr tst; |
|
1411 |
|
1412 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset, |
|
1413 attr->elem, attr->name, |
|
1414 attr->prefix); |
|
1415 if ((tst == attr) || (tst == NULL)) { |
|
1416 xmlChar fn[50]; |
|
1417 xmlChar *fulln; |
|
1418 |
|
1419 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50); |
|
1420 if (fulln == NULL) { |
|
1421 if ((ctxt->sax != NULL) && |
|
1422 (ctxt->sax->error != NULL)) |
|
1423 ctxt->sax->error(ctxt->userData, |
|
1424 EMBED_ERRTXT("SAX.xmlSAX2StartElement(): out of memory\n")); |
|
1425 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
1426 ctxt->instate = XML_PARSER_EOF; |
|
1427 ctxt->disableSAX = 1; |
|
1428 return; |
|
1429 } |
|
1430 |
|
1431 /* |
|
1432 * Check that the attribute is not declared in the |
|
1433 * serialization |
|
1434 */ |
|
1435 att = NULL; |
|
1436 if (atts != NULL) { |
|
1437 i = 0; |
|
1438 att = atts[i]; |
|
1439 while (att != NULL) { |
|
1440 if (xmlStrEqual(att, fulln)) |
|
1441 break; |
|
1442 i += 2; |
|
1443 att = atts[i]; |
|
1444 } |
|
1445 } |
|
1446 if (att == NULL) { |
|
1447 xmlSAX2AttributeInternal(ctxt, fulln, |
|
1448 attr->defaultValue, prefix); |
|
1449 } |
|
1450 if ((fulln != fn) && (fulln != attr->name)) |
|
1451 xmlFree(fulln); |
|
1452 } |
|
1453 } |
|
1454 } |
|
1455 attr = attr->nexth; |
|
1456 } |
|
1457 if (internal == 1) { |
|
1458 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, |
|
1459 name, prefix); |
|
1460 internal = 0; |
|
1461 goto process_external_subset; |
|
1462 } |
|
1463 } |
|
1464 } |
|
1465 |
|
1466 /** |
|
1467 * xmlSAX2StartElement: |
|
1468 * @param ctx the user data (XML parser context) |
|
1469 * @param fullname The element name, including namespace prefix |
|
1470 * @param atts An array of name/value attributes pairs, NULL terminated |
|
1471 * |
|
1472 * called when an opening tag has been processed. |
|
1473 */ |
|
1474 XMLPUBFUNEXPORT void |
|
1475 xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts) |
|
1476 { |
|
1477 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
1478 xmlNodePtr ret; |
|
1479 xmlNodePtr parent = ctxt->node; |
|
1480 xmlNsPtr ns; |
|
1481 xmlChar *name; |
|
1482 xmlChar *prefix; |
|
1483 const xmlChar *att; |
|
1484 const xmlChar *value; |
|
1485 int i; |
|
1486 |
|
1487 #ifdef DEBUG_SAX |
|
1488 xmlGenericError(xmlGenericErrorContext, |
|
1489 "SAX.xmlSAX2StartElement(%s)\n", fullname); |
|
1490 #endif |
|
1491 |
|
1492 /* |
|
1493 * First check on validity: |
|
1494 */ |
|
1495 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && |
|
1496 ((ctxt->myDoc->intSubset == NULL) || |
|
1497 ((ctxt->myDoc->intSubset->notations == NULL) && |
|
1498 (ctxt->myDoc->intSubset->elements == NULL) && |
|
1499 (ctxt->myDoc->intSubset->attributes == NULL) && |
|
1500 (ctxt->myDoc->intSubset->entities == NULL)))) { |
|
1501 xmlErrValid(ctxt, XML_ERR_NO_DTD, |
|
1502 EMBED_ERRTXT("Validation failed: no DTD found !"), NULL, NULL); |
|
1503 ctxt->validate = 0; |
|
1504 } |
|
1505 |
|
1506 |
|
1507 /* |
|
1508 * Split the full name into a namespace prefix and the tag name |
|
1509 */ |
|
1510 name = xmlSplitQName(ctxt, fullname, &prefix); |
|
1511 |
|
1512 |
|
1513 /* |
|
1514 * Note : the namespace resolution is deferred until the end of the |
|
1515 * attributes parsing, since local namespace can be defined as |
|
1516 * an attribute at this level. |
|
1517 */ |
|
1518 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL); |
|
1519 if (ret == NULL) { |
|
1520 if (prefix != NULL) |
|
1521 xmlFree(prefix); |
|
1522 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
1523 ctxt->instate = XML_PARSER_EOF; |
|
1524 ctxt->disableSAX = 1; |
|
1525 return; |
|
1526 } |
|
1527 if (ctxt->myDoc->children == NULL) { |
|
1528 #ifdef DEBUG_SAX_TREE |
|
1529 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name); |
|
1530 #endif |
|
1531 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); |
|
1532 } else if (parent == NULL) { |
|
1533 parent = ctxt->myDoc->children; |
|
1534 } |
|
1535 ctxt->nodemem = -1; |
|
1536 |
|
1537 #ifdef LIBXML_ENABLE_NODE_LINEINFO |
|
1538 if (ctxt->linenumbers) { |
|
1539 if (ctxt->input != NULL) { |
|
1540 if (ctxt->input->line < 65535) |
|
1541 ret->line = (short) ctxt->input->line; |
|
1542 else |
|
1543 ret->line = 65535; |
|
1544 } |
|
1545 } |
|
1546 #endif |
|
1547 /* |
|
1548 * We are parsing a new node. |
|
1549 */ |
|
1550 #ifdef DEBUG_SAX_TREE |
|
1551 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name); |
|
1552 #endif |
|
1553 nodePush(ctxt, ret); |
|
1554 |
|
1555 /* |
|
1556 * Link the child element |
|
1557 */ |
|
1558 if (parent != NULL) { |
|
1559 if (parent->type == XML_ELEMENT_NODE) { |
|
1560 #ifdef DEBUG_SAX_TREE |
|
1561 xmlGenericError(xmlGenericErrorContext,"adding child %s to %s\n", name, parent->name); |
|
1562 #endif |
|
1563 xmlAddChild(parent, ret); |
|
1564 } else { |
|
1565 #ifdef DEBUG_SAX_TREE |
|
1566 xmlGenericError(xmlGenericErrorContext,"adding sibling %s to ", name); |
|
1567 xmlDebugDumpOneNode(stderr, parent, 0); |
|
1568 #endif |
|
1569 xmlAddSibling(parent, ret); |
|
1570 } |
|
1571 } |
|
1572 |
|
1573 /* |
|
1574 * Insert all the defaulted attributes from the DTD especially namespaces |
|
1575 */ |
|
1576 |
|
1577 if ((!ctxt->html) && |
|
1578 ((ctxt->myDoc->intSubset != NULL) || (ctxt->myDoc->extSubset != NULL))) |
|
1579 { |
|
1580 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts); |
|
1581 } |
|
1582 |
|
1583 /* |
|
1584 * process all the attributes whose name start with "xmlns" |
|
1585 */ |
|
1586 if (atts != NULL) { |
|
1587 i = 0; |
|
1588 att = atts[i++]; |
|
1589 value = atts[i++]; |
|
1590 if (!ctxt->html) { |
|
1591 while ((att != NULL) && (value != NULL)) { |
|
1592 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') && |
|
1593 (att[3] == 'n') && (att[4] == 's')) |
|
1594 xmlSAX2AttributeInternal(ctxt, att, value, prefix); |
|
1595 |
|
1596 att = atts[i++]; |
|
1597 value = atts[i++]; |
|
1598 } |
|
1599 } |
|
1600 } |
|
1601 |
|
1602 /* |
|
1603 * Search the namespace, note that since the attributes have been |
|
1604 * processed, the local namespaces are available. |
|
1605 */ |
|
1606 ns = xmlSearchNs(ctxt->myDoc, ret, prefix); |
|
1607 if ((ns == NULL) && (parent != NULL)) |
|
1608 ns = xmlSearchNs(ctxt->myDoc, parent, prefix); |
|
1609 |
|
1610 if ((prefix != NULL) && (ns == NULL)) { |
|
1611 ns = xmlNewNs(ret, NULL, prefix); |
|
1612 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) |
|
1613 ctxt->sax->warning(ctxt->userData,EMBED_ERRTXT("Namespace prefix %s is not defined\n"), prefix); |
|
1614 } |
|
1615 |
|
1616 /* |
|
1617 * set the namespace node, making sure that if the default namspace |
|
1618 * is unbound on a parent we simply kee it NULL |
|
1619 */ |
|
1620 if ((ns != NULL) && (ns->href != NULL) && |
|
1621 ((ns->href[0] != 0) || (ns->prefix != NULL))) |
|
1622 xmlSetNs(ret, ns); |
|
1623 |
|
1624 /* |
|
1625 * process all the other attributes |
|
1626 */ |
|
1627 if (atts != NULL) { |
|
1628 i = 0; |
|
1629 att = atts[i++]; |
|
1630 value = atts[i++]; |
|
1631 if (ctxt->html) { |
|
1632 while (att != NULL) { |
|
1633 xmlSAX2AttributeInternal(ctxt, att, value, NULL); |
|
1634 att = atts[i++]; |
|
1635 value = atts[i++]; |
|
1636 } |
|
1637 } else { |
|
1638 while ((att != NULL) && (value != NULL)) { |
|
1639 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') || |
|
1640 (att[3] != 'n') || (att[4] != 's')) |
|
1641 xmlSAX2AttributeInternal(ctxt, att, value, NULL); |
|
1642 |
|
1643 /* |
|
1644 * Next ones |
|
1645 */ |
|
1646 att = atts[i++]; |
|
1647 value = atts[i++]; |
|
1648 } |
|
1649 } |
|
1650 } |
|
1651 |
|
1652 #ifdef LIBXML_VALID_ENABLED |
|
1653 /* |
|
1654 * If it's the Document root, finish the DTD validation and |
|
1655 * check the document root element for validity |
|
1656 */ |
|
1657 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) { |
|
1658 int chk; |
|
1659 |
|
1660 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); |
|
1661 if (chk <= 0) |
|
1662 ctxt->valid = 0; |
|
1663 if (chk < 0) |
|
1664 ctxt->wellFormed = 0; |
|
1665 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); |
|
1666 ctxt->vctxt.finishDtd = 1; |
|
1667 } |
|
1668 #endif /* LIBXML_VALID_ENABLED */ |
|
1669 |
|
1670 if (prefix != NULL) |
|
1671 xmlFree(prefix); |
|
1672 |
|
1673 } |
|
1674 |
|
1675 /** |
|
1676 * xmlSAX2EndElement: |
|
1677 * @param ctx the user data (XML parser context) |
|
1678 * @param name The element name |
|
1679 * |
|
1680 * called when the end of an element has been detected. |
|
1681 */ |
|
1682 XMLPUBFUNEXPORT void |
|
1683 xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED) |
|
1684 { |
|
1685 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
1686 //xmlParserNodeInfo node_info; |
|
1687 xmlNodePtr cur = ctxt->node; |
|
1688 |
|
1689 #ifdef DEBUG_SAX |
|
1690 if (name == NULL) |
|
1691 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n"); |
|
1692 else |
|
1693 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name); |
|
1694 #endif |
|
1695 |
|
1696 #ifdef XMLENGINE_ENABLE_PARSER_RECORD_INFO |
|
1697 /* Capture end position and add node */ |
|
1698 if (cur != NULL && ctxt->record_info) { |
|
1699 node_info.end_pos = ctxt->input->cur - ctxt->input->base; |
|
1700 node_info.end_line = ctxt->input->line; |
|
1701 node_info.node = cur; |
|
1702 xmlParserAddNodeInfo(ctxt, &node_info); |
|
1703 } |
|
1704 #endif // XMLENGINE_ENABLE_PARSER_RECORD_INFO |
|
1705 |
|
1706 ctxt->nodemem = -1; |
|
1707 |
|
1708 #ifdef LIBXML_VALID_ENABLED |
|
1709 if (ctxt->validate && ctxt->wellFormed && |
|
1710 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
1711 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, |
|
1712 cur); |
|
1713 #endif /* LIBXML_VALID_ENABLED */ |
|
1714 |
|
1715 |
|
1716 /* |
|
1717 * end of parsing of this node. |
|
1718 */ |
|
1719 #ifdef DEBUG_SAX_TREE |
|
1720 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name); |
|
1721 #endif |
|
1722 nodePop(ctxt); |
|
1723 } |
|
1724 #endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */ |
|
1725 |
|
1726 /* |
|
1727 * xmlSAX2TextNode: |
|
1728 * @param ctxt the parser context |
|
1729 * @param str the input string |
|
1730 * @param len the string length |
|
1731 * |
|
1732 * Remove the entities from an attribute value |
|
1733 * |
|
1734 * Returns the newly allocated string or NULL if not needed or error |
|
1735 */ |
|
1736 static xmlNodePtr |
|
1737 xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { |
|
1738 LOAD_GS(ctxt) |
|
1739 xmlNodePtr ret; |
|
1740 const xmlChar *intern = NULL; |
|
1741 |
|
1742 /* |
|
1743 * Allocate |
|
1744 */ |
|
1745 if (ctxt->freeElems != NULL) { |
|
1746 ret = ctxt->freeElems; |
|
1747 ctxt->freeElems = ret->next; |
|
1748 ctxt->freeElemsNr--; |
|
1749 } else { |
|
1750 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); |
|
1751 } |
|
1752 if (ret == NULL) { |
|
1753 OOM: |
|
1754 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
1755 ctxt->sax->error(ctxt->userData, EMBED_ERRTXT("SAX.xmlSAX2Characters(): out of memory\n")); |
|
1756 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
1757 ctxt->instate = XML_PARSER_EOF; |
|
1758 ctxt->disableSAX = 1; |
|
1759 return(NULL); |
|
1760 } |
|
1761 /* |
|
1762 * intern the formatting blanks found between tags, or the |
|
1763 * very short strings |
|
1764 */ |
|
1765 if (ctxt->dictNames) { |
|
1766 xmlChar cur = str[len]; |
|
1767 |
|
1768 if ((len <= 3) && ((cur == '"') || (cur == '\'') || |
|
1769 ((cur == '<') && (str[len + 1] != '!')))) |
|
1770 { |
|
1771 intern = xmlDictLookup(ctxt->dict, str, len); |
|
1772 } |
|
1773 else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') && |
|
1774 (str[len + 1] != '!')) |
|
1775 { |
|
1776 int i; |
|
1777 |
|
1778 for (i = 1;i < len;i++) { |
|
1779 if (!IS_BLANK_CH(str[i])) goto skip; |
|
1780 } |
|
1781 intern = xmlDictLookup(ctxt->dict, str, len); |
|
1782 } |
|
1783 } |
|
1784 skip: |
|
1785 memset(ret, 0, sizeof(xmlNode)); |
|
1786 ret->type = XML_TEXT_NODE; |
|
1787 |
|
1788 ret->name = xmlStringText; |
|
1789 if (intern == NULL) |
|
1790 { |
|
1791 ret->content = xmlStrndup(str, len); |
|
1792 { |
|
1793 if(OOM_FLAG) |
|
1794 { |
|
1795 if (ctxt->freeElems != NULL) |
|
1796 { |
|
1797 ctxt->freeElemsNr++; |
|
1798 ret->next = ctxt->freeElems; |
|
1799 ctxt->freeElems = ret; |
|
1800 } |
|
1801 else |
|
1802 { |
|
1803 xmlFreeNode(ret); |
|
1804 } |
|
1805 goto OOM; |
|
1806 } |
|
1807 } |
|
1808 } |
|
1809 else |
|
1810 ret->content = (xmlChar *) intern; |
|
1811 |
|
1812 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) |
|
1813 xmlRegisterNodeDefaultValue(ret); |
|
1814 return(ret); |
|
1815 } |
|
1816 |
|
1817 #ifdef LIBXML_VALID_ENABLED |
|
1818 /* |
|
1819 * xmlSAX2DecodeAttrEntities: |
|
1820 * @param ctxt the parser context |
|
1821 * @param str the input string |
|
1822 * @param len the string length |
|
1823 * |
|
1824 * Remove the entities from an attribute value |
|
1825 * |
|
1826 * Returns the newly allocated string or NULL if not needed or error |
|
1827 */ |
|
1828 static xmlChar * |
|
1829 xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, |
|
1830 const xmlChar *end) { |
|
1831 const xmlChar *in; |
|
1832 xmlChar *ret; |
|
1833 |
|
1834 in = str; |
|
1835 while (in < end) |
|
1836 if (*in++ == '&') |
|
1837 goto decode; |
|
1838 return(NULL); |
|
1839 decode: |
|
1840 ctxt->depth++; |
|
1841 ret = xmlStringLenDecodeEntities(ctxt, str, end - str, |
|
1842 XML_SUBSTITUTE_REF, 0,0,0); |
|
1843 ctxt->depth--; |
|
1844 return(ret); |
|
1845 } |
|
1846 #endif /* LIBXML_VALID_ENABLED */ |
|
1847 |
|
1848 |
|
1849 /** |
|
1850 * xmlSAX2AttributeNs: |
|
1851 * @param ctx the user data (XML parser context) |
|
1852 * @param localname the local name of the attribute |
|
1853 * @param prefix the attribute namespace prefix if available |
|
1854 * @param URI the attribute namespace name if available |
|
1855 * @param value Start of the attribute value |
|
1856 * @param valueend end of the attribute value |
|
1857 * |
|
1858 * Handle an attribute that has been read by the parser. |
|
1859 * The default handling is to convert the attribute into an |
|
1860 * DOM subtree and past it in a new xmlAttr element added to |
|
1861 * the element. |
|
1862 */ |
|
1863 static void |
|
1864 xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, |
|
1865 const xmlChar* localname, |
|
1866 const xmlChar* prefix, |
|
1867 const xmlChar* value, |
|
1868 const xmlChar* valueend) |
|
1869 { |
|
1870 LOAD_GS(ctxt) |
|
1871 xmlAttrPtr ret; |
|
1872 xmlNsPtr nameSpace = NULL; |
|
1873 xmlChar *dup = NULL; |
|
1874 |
|
1875 /* |
|
1876 * Note: if prefix == NULL, the attribute is not in the default namespace |
|
1877 */ |
|
1878 if (prefix != NULL) |
|
1879 nameSpace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); |
|
1880 |
|
1881 /* |
|
1882 * allocate the node |
|
1883 */ |
|
1884 if (ctxt->freeAttrs != NULL) |
|
1885 { |
|
1886 ret = ctxt->freeAttrs; |
|
1887 ctxt->freeAttrs = ret->next; |
|
1888 ctxt->freeAttrsNr--; |
|
1889 memset(ret, 0, sizeof(xmlAttr)); |
|
1890 ret->type = XML_ATTRIBUTE_NODE; |
|
1891 |
|
1892 ret->parent = ctxt->node; |
|
1893 ret->doc = ctxt->myDoc; |
|
1894 ret->ns = nameSpace; |
|
1895 |
|
1896 if (ctxt->dictNames) |
|
1897 ret->name = localname; |
|
1898 else |
|
1899 ret->name = xmlStrdup(localname); |
|
1900 |
|
1901 |
|
1902 if (ctxt->node->properties == NULL) { |
|
1903 ctxt->node->properties = ret; |
|
1904 } else { |
|
1905 xmlAttrPtr prev = ctxt->node->properties; |
|
1906 |
|
1907 while (prev->next != NULL) prev = prev->next; |
|
1908 prev->next = ret; |
|
1909 ret->prev = prev; |
|
1910 } |
|
1911 |
|
1912 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) |
|
1913 xmlRegisterNodeDefaultValue((xmlNodePtr)ret); |
|
1914 } else { |
|
1915 if (ctxt->dictNames) |
|
1916 ret = xmlNewNsPropEatName(ctxt->node, nameSpace, |
|
1917 (xmlChar *) localname, NULL); |
|
1918 else |
|
1919 ret = xmlNewNsProp(ctxt->node, nameSpace, localname, NULL); |
|
1920 if (ret == NULL) { |
|
1921 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
1922 ctxt->instate = XML_PARSER_EOF; |
|
1923 ctxt->disableSAX = 1; |
|
1924 return; |
|
1925 } |
|
1926 } |
|
1927 |
|
1928 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) |
|
1929 { |
|
1930 xmlNodePtr tmp; |
|
1931 |
|
1932 /* |
|
1933 * We know that if there is an entity reference, then |
|
1934 * the string has been dup'ed and terminates with 0 |
|
1935 * otherwise with ' or " |
|
1936 */ |
|
1937 if (*valueend != 0) { |
|
1938 tmp = xmlSAX2TextNode(ctxt, value, valueend - value); |
|
1939 if(OOM_FLAG) |
|
1940 { |
|
1941 xmlFree(dup); |
|
1942 return; |
|
1943 } |
|
1944 ret->children = tmp; |
|
1945 ret->last = tmp; |
|
1946 if (tmp != NULL) { |
|
1947 tmp->doc = ret->doc; |
|
1948 tmp->parent = (xmlNodePtr) ret; |
|
1949 } |
|
1950 } else { |
|
1951 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value, valueend - value); |
|
1952 |
|
1953 tmp = ret->children; |
|
1954 while (tmp != NULL) { |
|
1955 tmp->parent = (xmlNodePtr) ret; |
|
1956 if (tmp->next == NULL) |
|
1957 ret->last = tmp; |
|
1958 tmp = tmp->next; |
|
1959 } |
|
1960 } |
|
1961 } else if (value != NULL) { |
|
1962 xmlNodePtr tmp; |
|
1963 |
|
1964 tmp = xmlSAX2TextNode(ctxt, value, valueend - value); |
|
1965 ret->children = tmp; |
|
1966 ret->last = tmp; |
|
1967 if (tmp != NULL) { |
|
1968 tmp->doc = ret->doc; |
|
1969 tmp->parent = (xmlNodePtr) ret; |
|
1970 } |
|
1971 } |
|
1972 |
|
1973 #ifdef LIBXML_VALID_ENABLED |
|
1974 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed && |
|
1975 ctxt->myDoc && ctxt->myDoc->intSubset) { |
|
1976 /* |
|
1977 * If we don't substitute entities, the validation should be |
|
1978 * done on a value with replaced entities anyway. |
|
1979 */ |
|
1980 if (!ctxt->replaceEntities) { |
|
1981 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend); |
|
1982 if (dup == NULL) { |
|
1983 if (*valueend == 0) { |
|
1984 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, |
|
1985 ctxt->myDoc, ctxt->node, ret, value); |
|
1986 } else { |
|
1987 /* |
|
1988 * That should already be normalized. |
|
1989 * cheaper to finally allocate here than duplicate |
|
1990 * entry points in the full validation code |
|
1991 */ |
|
1992 dup = xmlStrndup(value, valueend - value); |
|
1993 |
|
1994 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, |
|
1995 ctxt->myDoc, ctxt->node, ret, dup); |
|
1996 } |
|
1997 } else { |
|
1998 /* |
|
1999 * dup now contains a string of the flattened attribute |
|
2000 * content with entities substitued. Check if we need to |
|
2001 * apply an extra layer of normalization. |
|
2002 * It need to be done twice ... it's an extra burden related |
|
2003 * to the ability to keep references in attributes |
|
2004 */ |
|
2005 if (ctxt->attsSpecial != NULL) { |
|
2006 xmlChar *nvalnorm; |
|
2007 xmlChar fn[50]; |
|
2008 xmlChar *fullname; |
|
2009 |
|
2010 fullname = xmlBuildQName(localname, prefix, fn, 50); |
|
2011 if (fullname != NULL) { |
|
2012 ctxt->vctxt.valid = 1; |
|
2013 nvalnorm = xmlValidCtxtNormalizeAttributeValue( |
|
2014 &ctxt->vctxt, ctxt->myDoc, |
|
2015 ctxt->node, fullname, dup); |
|
2016 if (ctxt->vctxt.valid != 1) |
|
2017 ctxt->valid = 0; |
|
2018 |
|
2019 if ((fullname != fn) && (fullname != localname)) |
|
2020 xmlFree(fullname); |
|
2021 if (nvalnorm != NULL) { |
|
2022 xmlFree(dup); |
|
2023 dup = nvalnorm; |
|
2024 } |
|
2025 } |
|
2026 } |
|
2027 |
|
2028 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, |
|
2029 ctxt->myDoc, ctxt->node, ret, dup); |
|
2030 } |
|
2031 } else { |
|
2032 /* |
|
2033 * if entities already have been substitued, then |
|
2034 * the attribute as passed is already normalized |
|
2035 */ |
|
2036 dup = xmlStrndup(value, valueend - value); |
|
2037 |
|
2038 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, |
|
2039 ctxt->myDoc, ctxt->node, ret, dup); |
|
2040 } |
|
2041 } else |
|
2042 #endif /* LIBXML_VALID_ENABLED */ |
|
2043 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) && |
|
2044 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) || |
|
2045 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) { |
|
2046 /* |
|
2047 * when validating, the ID registration is done at the attribute |
|
2048 * validation level. Otherwise we have to do specific handling here. |
|
2049 */ |
|
2050 if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) { |
|
2051 /* might be worth duplicate entry points and not copy */ |
|
2052 if (dup == NULL) |
|
2053 dup = xmlStrndup(value, valueend - value); |
|
2054 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); |
|
2055 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) { |
|
2056 if (dup == NULL) |
|
2057 dup = xmlStrndup(value, valueend - value); |
|
2058 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret); |
|
2059 } else if ((prefix == ctxt->str_xml) && |
|
2060 (localname[0] == 'i') && (localname[1] == 'd') && |
|
2061 (localname[2] == 0)) { |
|
2062 /* |
|
2063 * Add the xml:id value |
|
2064 * |
|
2065 * Open issue: normalization of the value. |
|
2066 */ |
|
2067 if (dup == NULL) |
|
2068 dup = xmlStrndup(value, valueend - value); |
|
2069 if (xmlValidateNCName(dup, 1) != 0) { |
|
2070 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE, |
|
2071 EMBED_ERRTXT("xml:id : attribute value %s is not an NCName\n"), |
|
2072 (const char *) dup, NULL); |
|
2073 } |
|
2074 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret); |
|
2075 } |
|
2076 } |
|
2077 if (dup != NULL) |
|
2078 xmlFree(dup); |
|
2079 } |
|
2080 |
|
2081 /** |
|
2082 * xmlSAX2StartElementNs: |
|
2083 * @param ctx the user data (XML parser context) |
|
2084 * @param localname the local name of the element |
|
2085 * @param prefix the element namespace prefix if available |
|
2086 * @param URI the element namespace name if available |
|
2087 * @param nb_namespaces number of namespace definitions on that node |
|
2088 * @param namespaces pointer to the array of prefix/URI pairs namespace definitions |
|
2089 * @param nb_attributes the number of attributes on that node |
|
2090 * @param nb_defaulted the number of defaulted attributes. |
|
2091 * @param attributes pointer to the array of (localname/prefix/URI/value/end) |
|
2092 * attribute values. |
|
2093 * |
|
2094 * SAX2 callback when an element start has been detected by the parser. |
|
2095 * It provides the namespace informations for the element, as well as |
|
2096 * the new namespace declarations on the element. |
|
2097 */ |
|
2098 XMLPUBFUNEXPORT void |
|
2099 xmlSAX2StartElementNs(void* ctx, |
|
2100 const xmlChar *localname, |
|
2101 const xmlChar *prefix, |
|
2102 const xmlChar *URI, |
|
2103 int nb_namespaces, |
|
2104 const xmlChar **namespaces, |
|
2105 int nb_attributes, |
|
2106 int nb_defaulted, |
|
2107 const xmlChar **attributes) |
|
2108 { |
|
2109 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
2110 xmlNodePtr ret; |
|
2111 xmlNodePtr parent = ctxt->node; |
|
2112 xmlNsPtr last = NULL, ns; |
|
2113 const xmlChar *uri, *pref; |
|
2114 int i, j; |
|
2115 LOAD_GS_SAFE_CTXT(ctxt) |
|
2116 |
|
2117 |
|
2118 /* |
|
2119 * First check on validity: |
|
2120 */ |
|
2121 if (ctxt->validate && |
|
2122 (ctxt->myDoc->extSubset == NULL) && |
|
2123 ((ctxt->myDoc->intSubset == NULL) |
|
2124 || |
|
2125 ((ctxt->myDoc->intSubset->notations == NULL) && |
|
2126 (ctxt->myDoc->intSubset->elements == NULL) && |
|
2127 (ctxt->myDoc->intSubset->attributes == NULL)&& |
|
2128 (ctxt->myDoc->intSubset->entities == NULL) |
|
2129 ) |
|
2130 ) |
|
2131 ) |
|
2132 { |
|
2133 xmlErrValid(ctxt, XML_ERR_NO_DTD, EMBED_ERRTXT("Validation failed: no DTD found !"), NULL, NULL); |
|
2134 ctxt->validate = 0; |
|
2135 } |
|
2136 |
|
2137 /* |
|
2138 * allocate the node |
|
2139 */ |
|
2140 if (ctxt->freeElems != NULL) { |
|
2141 ret = ctxt->freeElems; |
|
2142 ctxt->freeElems = ret->next; |
|
2143 ctxt->freeElemsNr--; |
|
2144 memset(ret, 0, sizeof(xmlNode)); |
|
2145 ret->type = XML_ELEMENT_NODE; |
|
2146 |
|
2147 if (ctxt->dictNames) |
|
2148 ret->name = localname; |
|
2149 else |
|
2150 ret->name = xmlStrdup(localname); |
|
2151 |
|
2152 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) |
|
2153 xmlRegisterNodeDefaultValue(ret); |
|
2154 } else { |
|
2155 if (ctxt->dictNames) |
|
2156 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, |
|
2157 (xmlChar *) localname, NULL); |
|
2158 else |
|
2159 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL); |
|
2160 |
|
2161 if (ret == NULL) { |
|
2162 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
2163 ctxt->instate = XML_PARSER_EOF; |
|
2164 ctxt->disableSAX = 1; |
|
2165 return; |
|
2166 } |
|
2167 } |
|
2168 #ifdef LIBXML_ENABLE_NODE_LINEINFO |
|
2169 if (ctxt->linenumbers) { |
|
2170 if (ctxt->input != NULL) { |
|
2171 if (ctxt->input->line < 65535) |
|
2172 ret->line = (short) ctxt->input->line; |
|
2173 else |
|
2174 ret->line = 65535; |
|
2175 } |
|
2176 } |
|
2177 #endif |
|
2178 |
|
2179 if (ctxt->myDoc->children == NULL) { |
|
2180 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); |
|
2181 } else if (parent == NULL) { |
|
2182 parent = ctxt->myDoc->children; |
|
2183 } |
|
2184 /* |
|
2185 * Build the namespace list |
|
2186 */ |
|
2187 for (i = 0,j = 0;j < nb_namespaces;j++) |
|
2188 { |
|
2189 pref = namespaces[i++]; |
|
2190 uri = namespaces[i++]; |
|
2191 // NULL passed in order to avoid uniqueness check in xmlNewNs(), |
|
2192 ns = xmlNewNs(NULL, uri, pref); |
|
2193 // ... but then we need to link new Ns node manually |
|
2194 if (ns != NULL) { |
|
2195 if (last == NULL) { |
|
2196 ret->nsDef = last = ns; |
|
2197 } else { |
|
2198 last->next = ns; |
|
2199 last = ns; |
|
2200 } |
|
2201 if ((URI != NULL) && (prefix == pref)) |
|
2202 ret->ns = ns; |
|
2203 } else { |
|
2204 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
2205 ctxt->instate = XML_PARSER_EOF; |
|
2206 ctxt->disableSAX = 1; |
|
2207 //DONE: OOM: cleanup: |
|
2208 if(ctxt->myDoc->children != ret) |
|
2209 xmlFreeNode(ret); // it was not yet inserted in myDoc |
|
2210 return; |
|
2211 } |
|
2212 #ifdef LIBXML_VALID_ENABLED |
|
2213 if (ctxt->validate && (!ctxt->html) && ctxt->wellFormed && |
|
2214 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
2215 { |
|
2216 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc, |
|
2217 ret, prefix, ns, uri); |
|
2218 } |
|
2219 #endif /* LIBXML_VALID_ENABLED */ |
|
2220 } // for (i = 0,j = 0;j < nb_namespaces;j++) |
|
2221 |
|
2222 ctxt->nodemem = -1; |
|
2223 |
|
2224 /* |
|
2225 * We are parsing a new node. |
|
2226 */ |
|
2227 nodePush(ctxt, ret); |
|
2228 |
|
2229 /* |
|
2230 * Link the child element |
|
2231 */ |
|
2232 if (parent != NULL) { |
|
2233 if (parent->type == XML_ELEMENT_NODE) { |
|
2234 xmlAddChild(parent, ret); |
|
2235 } else { |
|
2236 xmlAddSibling(parent, ret); |
|
2237 } |
|
2238 } |
|
2239 |
|
2240 /* |
|
2241 * Insert the defaulted attributes from the DTD only if requested: |
|
2242 */ |
|
2243 if ((nb_defaulted != 0) && |
|
2244 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0)) |
|
2245 { |
|
2246 nb_attributes -= nb_defaulted; |
|
2247 } |
|
2248 |
|
2249 /* |
|
2250 * Search the namespace if it wasn't already found |
|
2251 */ |
|
2252 if ((URI != NULL) && (ret->ns == NULL)) { |
|
2253 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix); |
|
2254 if (ret->ns == NULL) { |
|
2255 ns = xmlNewNs(ret, NULL, prefix); |
|
2256 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) |
|
2257 ctxt->sax->warning(ctxt->userData, |
|
2258 EMBED_ERRTXT("Namespace prefix %s was not found\n"), prefix); |
|
2259 } |
|
2260 } |
|
2261 |
|
2262 /* |
|
2263 * process all the other attributes |
|
2264 */ |
|
2265 if (nb_attributes > 0) { |
|
2266 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) { |
|
2267 |
|
2268 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1], |
|
2269 attributes[j+3], attributes[j+4]); |
|
2270 if(OOM_FLAG) |
|
2271 { |
|
2272 return; |
|
2273 } |
|
2274 } |
|
2275 } |
|
2276 |
|
2277 #ifdef LIBXML_VALID_ENABLED |
|
2278 /* |
|
2279 * If it's the Document root, finish the DTD validation and |
|
2280 * check the document root element for validity |
|
2281 */ |
|
2282 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) { |
|
2283 int chk; |
|
2284 |
|
2285 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); |
|
2286 if (chk <= 0) |
|
2287 ctxt->valid = 0; |
|
2288 if (chk < 0) |
|
2289 ctxt->wellFormed = 0; |
|
2290 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); |
|
2291 ctxt->vctxt.finishDtd = 1; |
|
2292 } |
|
2293 #endif /* LIBXML_VALID_ENABLED */ |
|
2294 } |
|
2295 |
|
2296 /** |
|
2297 * xmlSAX2EndElementNs: |
|
2298 * @param ctx the user data (XML parser context) |
|
2299 * @param localname the local name of the element |
|
2300 * @param prefix the element namespace prefix if available |
|
2301 * @param URI the element namespace name if available |
|
2302 * |
|
2303 * SAX2 callback when an element end has been detected by the parser. |
|
2304 * It provides the namespace informations for the element. |
|
2305 */ |
|
2306 |
|
2307 XMLPUBFUNEXPORT void |
|
2308 xmlSAX2EndElementNs(void *ctx, |
|
2309 const xmlChar * localname ATTRIBUTE_UNUSED, |
|
2310 const xmlChar * prefix ATTRIBUTE_UNUSED, |
|
2311 const xmlChar * URI ATTRIBUTE_UNUSED) |
|
2312 { |
|
2313 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
2314 #if defined(LIBXML_VALID_ENABLED) || defined(XMLENGINE_ENABLE_PARSER_RECORD_INFO) |
|
2315 xmlNodePtr cur = ctxt->node; |
|
2316 #endif |
|
2317 |
|
2318 #ifdef XMLENGINE_ENABLE_PARSER_RECORD_INFO |
|
2319 { |
|
2320 xmlParserNodeInfo node_info; |
|
2321 |
|
2322 /* Capture end position and add node */ |
|
2323 if ((ctxt->record_info) && (cur != NULL)) { |
|
2324 node_info.end_pos = ctxt->input->cur - ctxt->input->base; |
|
2325 node_info.end_line = ctxt->input->line; |
|
2326 node_info.node = cur; |
|
2327 xmlParserAddNodeInfo(ctxt, &node_info); |
|
2328 } |
|
2329 } |
|
2330 #endif |
|
2331 |
|
2332 ctxt->nodemem = -1; |
|
2333 |
|
2334 #ifdef LIBXML_VALID_ENABLED |
|
2335 if (ctxt->validate && ctxt->wellFormed && |
|
2336 ctxt->myDoc && ctxt->myDoc->intSubset) |
|
2337 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur); |
|
2338 #endif /* LIBXML_VALID_ENABLED */ |
|
2339 |
|
2340 /* |
|
2341 * end of parsing of this node. |
|
2342 */ |
|
2343 nodePop(ctxt); |
|
2344 } |
|
2345 |
|
2346 /** |
|
2347 * xmlSAX2Reference: |
|
2348 * @param ctx the user data (XML parser context) |
|
2349 * @param name The entity name |
|
2350 * |
|
2351 * called when an entity xmlSAX2Reference is detected. |
|
2352 */ |
|
2353 XMLPUBFUNEXPORT void |
|
2354 xmlSAX2Reference(void *ctx, const xmlChar *name) |
|
2355 { |
|
2356 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
2357 xmlNodePtr ret; |
|
2358 |
|
2359 #ifdef DEBUG_SAX |
|
2360 xmlGenericError(xmlGenericErrorContext, |
|
2361 "SAX.xmlSAX2Reference(%s)\n", name); |
|
2362 #endif |
|
2363 if (name[0] == '#') |
|
2364 ret = xmlNewCharRef(ctxt->myDoc, name); |
|
2365 else |
|
2366 ret = xmlNewReference(ctxt->myDoc, name); |
|
2367 #ifdef DEBUG_SAX_TREE |
|
2368 xmlGenericError(xmlGenericErrorContext, |
|
2369 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name); |
|
2370 #endif |
|
2371 xmlAddChild(ctxt->node, ret); |
|
2372 } |
|
2373 |
|
2374 /** |
|
2375 * xmlSAX2Characters: |
|
2376 * @param ctx the user data (XML parser context) |
|
2377 * @param ch a xmlChar string |
|
2378 * @param len the number of xmlChar |
|
2379 * |
|
2380 * receiving some chars from the parser. |
|
2381 */ |
|
2382 XMLPUBFUNEXPORT void |
|
2383 xmlSAX2Characters(void *ctx, const xmlChar *ch, int len) |
|
2384 { |
|
2385 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
2386 xmlNodePtr lastChild; |
|
2387 |
|
2388 /* |
|
2389 * SYMBIAN DEF130695 FIX : Ensuring that CTX(xml buffer context) is valid or not. The CTX is being considered |
|
2390 * here while receiving parsed characters using SAX parsing mechanism. |
|
2391 */ |
|
2392 if(ctx == NULL) |
|
2393 return; |
|
2394 |
|
2395 |
|
2396 #ifdef DEBUG_SAX |
|
2397 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len); |
|
2398 #endif |
|
2399 /* |
|
2400 * Handle the data if any. If there is no child |
|
2401 * add it as content, otherwise if the last child is text, |
|
2402 * concatenate it, else create a new node of type text. |
|
2403 */ |
|
2404 |
|
2405 if (ctxt->node == NULL) { |
|
2406 #ifdef DEBUG_SAX_TREE |
|
2407 xmlGenericError(xmlGenericErrorContext, "add chars: ctxt->node == NULL !\n"); |
|
2408 #endif |
|
2409 return; |
|
2410 } |
|
2411 lastChild = ctxt->node->last; |
|
2412 #ifdef DEBUG_SAX_TREE |
|
2413 xmlGenericError(xmlGenericErrorContext, "add chars to %s \n", ctxt->node->name); |
|
2414 #endif |
|
2415 |
|
2416 /* |
|
2417 * Here we needed an accelerator mechanism in case of very large |
|
2418 * elements. Use an attribute in the structure !!! |
|
2419 */ |
|
2420 if (lastChild == NULL) { |
|
2421 lastChild = xmlSAX2TextNode(ctxt, ch, len); |
|
2422 |
|
2423 if (lastChild != NULL) { |
|
2424 ctxt->node->children = lastChild; |
|
2425 ctxt->node->last = lastChild; |
|
2426 lastChild->parent = ctxt->node; |
|
2427 lastChild->doc = ctxt->node->doc; |
|
2428 ctxt->nodelen = len; |
|
2429 ctxt->nodemem = len + 1; |
|
2430 } |
|
2431 } else { |
|
2432 int coalesceText = (lastChild != NULL) && |
|
2433 (lastChild->type == XML_TEXT_NODE) && |
|
2434 (lastChild->name == xmlStringText); |
|
2435 if ((coalesceText) && (ctxt->nodemem != 0)) { |
|
2436 /* |
|
2437 * The whole point of maintaining nodelen and nodemem, |
|
2438 * xmlTextConcat is too costly, i.e. compute length, |
|
2439 * reallocate a new buffer, move data, append ch. Here |
|
2440 * We try to minimaze realloc() uses and avoid copying |
|
2441 * and recomputing length over and over. |
|
2442 */ |
|
2443 if ((ctxt->nodemem == ctxt->nodelen + 1) && |
|
2444 (xmlDictOwns(ctxt->dict, lastChild->content))) |
|
2445 { |
|
2446 lastChild->content = xmlStrdup(lastChild->content); |
|
2447 } |
|
2448 if (ctxt->nodelen + len >= ctxt->nodemem) { |
|
2449 xmlChar *newbuf; |
|
2450 int size; |
|
2451 |
|
2452 size = ctxt->nodemem + len; |
|
2453 size *= 2; |
|
2454 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size); |
|
2455 if (newbuf == NULL) { |
|
2456 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
2457 ctxt->sax->error(ctxt->userData, EMBED_ERRTXT("SAX.xmlSAX2Characters(): out of memory\n")); |
|
2458 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
2459 ctxt->instate = XML_PARSER_EOF; |
|
2460 ctxt->disableSAX = 1; |
|
2461 return; |
|
2462 } |
|
2463 ctxt->nodemem = size; |
|
2464 lastChild->content = newbuf; |
|
2465 } |
|
2466 memcpy(&lastChild->content[ctxt->nodelen], ch, len); |
|
2467 ctxt->nodelen += len; |
|
2468 lastChild->content[ctxt->nodelen] = 0; |
|
2469 } else if (coalesceText) { |
|
2470 if (xmlTextConcat(lastChild, ch, len)) { |
|
2471 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) |
|
2472 ctxt->sax->error(ctxt->userData, EMBED_ERRTXT("SAX.xmlSAX2Characters(): out of memory\n")); |
|
2473 ctxt->errNo = XML_ERR_NO_MEMORY; |
|
2474 ctxt->instate = XML_PARSER_EOF; |
|
2475 ctxt->disableSAX = 1; |
|
2476 } |
|
2477 if (ctxt->node->children != NULL) { |
|
2478 ctxt->nodelen = xmlStrlen(lastChild->content); |
|
2479 ctxt->nodemem = ctxt->nodelen + 1; |
|
2480 } |
|
2481 } else { |
|
2482 /* Mixed content, first time */ |
|
2483 lastChild = xmlSAX2TextNode(ctxt, ch, len); |
|
2484 if (lastChild != NULL) { |
|
2485 xmlAddChild(ctxt->node, lastChild); |
|
2486 if (ctxt->node->children != NULL) { |
|
2487 ctxt->nodelen = len; |
|
2488 ctxt->nodemem = len + 1; |
|
2489 } |
|
2490 } |
|
2491 } |
|
2492 } |
|
2493 } |
|
2494 |
|
2495 /** |
|
2496 * xmlSAX2IgnorableWhitespace: |
|
2497 * @param ctx the user data (XML parser context) |
|
2498 * @param ch a xmlChar string |
|
2499 * @param len the number of xmlChar |
|
2500 * |
|
2501 * receiving some ignorable whitespaces from the parser. |
|
2502 * UNUSED: by default the DOM building will use xmlSAX2Characters |
|
2503 */ |
|
2504 XMLPUBFUNEXPORT void |
|
2505 xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED) |
|
2506 { |
|
2507 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */ |
|
2508 #ifdef DEBUG_SAX |
|
2509 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len); |
|
2510 #endif |
|
2511 if(ctx) return; // just to use ctx |
|
2512 } |
|
2513 |
|
2514 /** |
|
2515 * xmlSAX2ProcessingInstruction: |
|
2516 * @param ctx the user data (XML parser context) |
|
2517 * @param target the target name |
|
2518 * @param data the PI data's |
|
2519 * |
|
2520 * A processing instruction has been parsed. |
|
2521 */ |
|
2522 XMLPUBFUNEXPORT void |
|
2523 xmlSAX2ProcessingInstruction(void *ctx, |
|
2524 const xmlChar *target, |
|
2525 const xmlChar *data) |
|
2526 { |
|
2527 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
2528 xmlNodePtr ret; |
|
2529 xmlNodePtr parent = ctxt->node; |
|
2530 |
|
2531 #ifdef DEBUG_SAX |
|
2532 xmlGenericError(xmlGenericErrorContext, |
|
2533 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data); |
|
2534 #endif |
|
2535 |
|
2536 ret = xmlNewPI(target, data); |
|
2537 if (!ret) |
|
2538 return; |
|
2539 parent = ctxt->node; |
|
2540 |
|
2541 if (ctxt->inSubset == 1) { |
|
2542 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); |
|
2543 return; |
|
2544 } else |
|
2545 if (ctxt->inSubset == 2) { |
|
2546 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); |
|
2547 return; |
|
2548 } |
|
2549 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { |
|
2550 #ifdef DEBUG_SAX_TREE |
|
2551 xmlGenericError(xmlGenericErrorContext,"Setting PI %s as root\n", target); |
|
2552 #endif |
|
2553 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); |
|
2554 return; |
|
2555 } |
|
2556 if (parent->type == XML_ELEMENT_NODE) { |
|
2557 #ifdef DEBUG_SAX_TREE |
|
2558 xmlGenericError(xmlGenericErrorContext, |
|
2559 "adding PI %s child to %s\n", target, parent->name); |
|
2560 #endif |
|
2561 xmlAddChild(parent, ret); |
|
2562 } else { |
|
2563 #ifdef DEBUG_SAX_TREE |
|
2564 xmlGenericError(xmlGenericErrorContext, "adding PI %s sibling to ", target); |
|
2565 xmlDebugDumpOneNode(stderr, parent, 0); |
|
2566 #endif |
|
2567 xmlAddSibling(parent, ret); |
|
2568 } |
|
2569 } |
|
2570 |
|
2571 /** |
|
2572 * xmlSAX2Comment: |
|
2573 * @param ctx the user data (XML parser context) |
|
2574 * @param value the xmlSAX2Comment content |
|
2575 * |
|
2576 * A xmlSAX2Comment has been parsed. |
|
2577 */ |
|
2578 XMLPUBFUNEXPORT void |
|
2579 xmlSAX2Comment(void *ctx, const xmlChar *value) |
|
2580 { |
|
2581 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
2582 xmlNodePtr ret; |
|
2583 xmlNodePtr parent = ctxt->node; |
|
2584 |
|
2585 #ifdef DEBUG_SAX |
|
2586 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value); |
|
2587 #endif |
|
2588 ret = xmlNewDocComment(ctxt->myDoc, value); |
|
2589 if (ret == NULL) return; |
|
2590 |
|
2591 |
|
2592 if (ctxt->inSubset == 1) { |
|
2593 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret); |
|
2594 return; |
|
2595 } else if (ctxt->inSubset == 2) { |
|
2596 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret); |
|
2597 return; |
|
2598 } |
|
2599 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) { |
|
2600 #ifdef DEBUG_SAX_TREE |
|
2601 xmlGenericError(xmlGenericErrorContext, |
|
2602 "Setting xmlSAX2Comment as root\n"); |
|
2603 #endif |
|
2604 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); |
|
2605 return; |
|
2606 } |
|
2607 if (parent->type == XML_ELEMENT_NODE) { |
|
2608 #ifdef DEBUG_SAX_TREE |
|
2609 xmlGenericError(xmlGenericErrorContext, |
|
2610 "adding xmlSAX2Comment child to %s\n", parent->name); |
|
2611 #endif |
|
2612 xmlAddChild(parent, ret); |
|
2613 } else { |
|
2614 #ifdef DEBUG_SAX_TREE |
|
2615 xmlGenericError(xmlGenericErrorContext, |
|
2616 "adding xmlSAX2Comment sibling to "); |
|
2617 xmlDebugDumpOneNode(stderr, parent, 0); |
|
2618 #endif |
|
2619 xmlAddSibling(parent, ret); |
|
2620 } |
|
2621 } |
|
2622 |
|
2623 /** |
|
2624 * xmlSAX2CDataBlock: |
|
2625 * @param ctx the user data (XML parser context) |
|
2626 * @param value The pcdata content |
|
2627 * @param len the block length |
|
2628 * |
|
2629 * called when a pcdata block has been parsed |
|
2630 */ |
|
2631 XMLPUBFUNEXPORT void |
|
2632 xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len) |
|
2633 { |
|
2634 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; |
|
2635 xmlNodePtr ret, lastChild; |
|
2636 |
|
2637 #ifdef DEBUG_SAX |
|
2638 xmlGenericError(xmlGenericErrorContext,"SAX.pcdata(%.10s, %d)\n", value, len); |
|
2639 #endif |
|
2640 lastChild = xmlGetLastChild(ctxt->node); |
|
2641 #ifdef DEBUG_SAX_TREE |
|
2642 xmlGenericError(xmlGenericErrorContext,"add chars to %s \n", ctxt->node->name); |
|
2643 #endif |
|
2644 if ((lastChild != NULL) && |
|
2645 (lastChild->type == XML_CDATA_SECTION_NODE)) |
|
2646 { |
|
2647 xmlTextConcat(lastChild, value, len); |
|
2648 } else { |
|
2649 ret = xmlNewCDataBlock(ctxt->myDoc, value, len); |
|
2650 xmlAddChild(ctxt->node, ret); |
|
2651 } |
|
2652 } |
|
2653 |
|
2654 #ifdef LIBXML_SAX1_ENABLED |
|
2655 /** |
|
2656 * xmlSAXDefaultVersion: |
|
2657 * @param version the version, 1 or 2 |
|
2658 * |
|
2659 * Set the default version of SAX used globally by the library. |
|
2660 * Note that this may not be a good thing to do from a library |
|
2661 * it is better to use xmlSAXVersion() to set up specifically the |
|
2662 * version for a given parsing context. |
|
2663 * |
|
2664 * Returns the previous value in case of success and -1 in case of error. |
|
2665 */ |
|
2666 XMLPUBFUNEXPORT int |
|
2667 xmlSAXDefaultVersion(int version) |
|
2668 { |
|
2669 LOAD_GS_DIRECT |
|
2670 int ret = xmlSAX2DefaultVersionValue; |
|
2671 |
|
2672 if ((version != 1) && (version != 2)) |
|
2673 return(-1); |
|
2674 xmlSAX2DefaultVersionValue = version; |
|
2675 return(ret); |
|
2676 } |
|
2677 #endif /* LIBXML_SAX1_ENABLED */ |
|
2678 |
|
2679 /** |
|
2680 * xmlSAXVersion: |
|
2681 * @param hdlr the SAX handler |
|
2682 * @param version the version, 1 or 2 |
|
2683 * |
|
2684 * Initialize the default XML SAX handler according to the version |
|
2685 * |
|
2686 * Returns 0 in case of success and -1 in case of error. |
|
2687 * |
|
2688 * OOM: never |
|
2689 */ |
|
2690 XMLPUBFUNEXPORT int |
|
2691 xmlSAXVersion(xmlSAXHandler *hdlr, int version) |
|
2692 { |
|
2693 if (hdlr == NULL) return(-1); |
|
2694 if (version == 2) { |
|
2695 hdlr->startElement = NULL; |
|
2696 hdlr->endElement = NULL; |
|
2697 hdlr->startElementNs = xmlSAX2StartElementNs; |
|
2698 hdlr->endElementNs = xmlSAX2EndElementNs; |
|
2699 hdlr->serror = NULL; |
|
2700 hdlr->initialized = XML_SAX2_MAGIC; |
|
2701 #ifdef LIBXML_SAX1_ENABLED |
|
2702 } else if (version == 1) { |
|
2703 hdlr->startElement = xmlSAX2StartElement; |
|
2704 hdlr->endElement = xmlSAX2EndElement; |
|
2705 hdlr->initialized = 1; |
|
2706 #endif /* LIBXML_SAX1_ENABLED */ |
|
2707 } else |
|
2708 return(-1); |
|
2709 hdlr->internalSubset = xmlSAX2InternalSubset; |
|
2710 hdlr->externalSubset = xmlSAX2ExternalSubset; |
|
2711 hdlr->isStandalone = xmlSAX2IsStandalone; |
|
2712 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; |
|
2713 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; |
|
2714 hdlr->resolveEntity = xmlSAX2ResolveEntity; |
|
2715 hdlr->getEntity = xmlSAX2GetEntity; |
|
2716 hdlr->getParameterEntity = xmlSAX2GetParameterEntity; |
|
2717 hdlr->entityDecl = xmlSAX2EntityDecl; |
|
2718 hdlr->attributeDecl = xmlSAX2AttributeDecl; |
|
2719 hdlr->elementDecl = xmlSAX2ElementDecl; |
|
2720 hdlr->notationDecl = xmlSAX2NotationDecl; |
|
2721 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl; |
|
2722 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; |
|
2723 hdlr->startDocument = xmlSAX2StartDocument; |
|
2724 hdlr->endDocument = xmlSAX2EndDocument; |
|
2725 hdlr->reference = xmlSAX2Reference; |
|
2726 hdlr->characters = xmlSAX2Characters; |
|
2727 hdlr->cdataBlock = xmlSAX2CDataBlock; |
|
2728 hdlr->ignorableWhitespace = xmlSAX2Characters; |
|
2729 hdlr->processingInstruction = xmlSAX2ProcessingInstruction; |
|
2730 hdlr->comment = xmlSAX2Comment; |
|
2731 // XMLENGINE: MODIFIED CODE |
|
2732 // preprocessor directive is used for managing error callbacks |
|
2733 #ifdef _DEBUG_LIBXML |
|
2734 hdlr->warning = xmlParserWarning; |
|
2735 hdlr->error = xmlParserError; |
|
2736 hdlr->fatalError = xmlParserError; |
|
2737 #else |
|
2738 hdlr->warning = NULL; |
|
2739 hdlr->error = NULL; |
|
2740 hdlr->fatalError = NULL; |
|
2741 #endif |
|
2742 // XMLENGINE: BEGINE NEW CODE |
|
2743 // These should be nullified for DOMParser |
|
2744 hdlr->startPrefixMapping = NULL; |
|
2745 hdlr->endPrefixMapping = NULL; |
|
2746 // XMLENGINE: END NEW CODE |
|
2747 |
|
2748 return(0); |
|
2749 } |
|
2750 |
|
2751 #ifdef LIBXML_HTML_ENABLED |
|
2752 /** |
|
2753 * xmlSAX2InitHtmlDefaultSAXHandler: |
|
2754 * @param hdlr the SAX handler |
|
2755 * |
|
2756 * Initialize the default HTML SAX2 handler |
|
2757 */ |
|
2758 void |
|
2759 xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr) |
|
2760 { |
|
2761 if(hdlr->initialized != 0) |
|
2762 return; |
|
2763 |
|
2764 hdlr->internalSubset = xmlSAX2InternalSubset; |
|
2765 hdlr->externalSubset = NULL; |
|
2766 hdlr->isStandalone = NULL; |
|
2767 hdlr->hasInternalSubset = NULL; |
|
2768 hdlr->hasExternalSubset = NULL; |
|
2769 hdlr->resolveEntity = NULL; |
|
2770 hdlr->getEntity = xmlSAX2GetEntity; |
|
2771 hdlr->getParameterEntity = NULL; |
|
2772 hdlr->entityDecl = NULL; |
|
2773 hdlr->attributeDecl = NULL; |
|
2774 hdlr->elementDecl = NULL; |
|
2775 hdlr->notationDecl = NULL; |
|
2776 hdlr->unparsedEntityDecl = NULL; |
|
2777 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; |
|
2778 hdlr->startDocument = xmlSAX2StartDocument; |
|
2779 hdlr->endDocument = xmlSAX2EndDocument; |
|
2780 hdlr->startElement = xmlSAX2StartElement; |
|
2781 hdlr->endElement = xmlSAX2EndElement; |
|
2782 hdlr->reference = NULL; |
|
2783 hdlr->characters = xmlSAX2Characters; |
|
2784 hdlr->cdataBlock = xmlSAX2CDataBlock; |
|
2785 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; |
|
2786 hdlr->processingInstruction = NULL; |
|
2787 hdlr->comment = xmlSAX2Comment; |
|
2788 hdlr->warning = xmlParserWarning; |
|
2789 hdlr->error = xmlParserError; |
|
2790 hdlr->fatalError = xmlParserError; |
|
2791 |
|
2792 hdlr->initialized = 1; |
|
2793 } |
|
2794 |
|
2795 |
|
2796 /** |
|
2797 * htmlDefaultSAXHandlerInit: |
|
2798 * |
|
2799 * Initialize the default SAX handler |
|
2800 */ |
|
2801 void |
|
2802 htmlDefaultSAXHandlerInit(void) |
|
2803 { |
|
2804 // XMLENGINE: disabled: HTML is never parsed |
|
2805 // xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler); |
|
2806 } |
|
2807 #endif |
|
2808 |
|
2809 |
|
2810 /** |
|
2811 * xmlSAX2InitDefaultSAXHandler: |
|
2812 * @param hdlr the SAX handler |
|
2813 * @param warning flag if non-zero sets the handler warning procedure |
|
2814 * |
|
2815 * Initialize the default XML SAX2 handler |
|
2816 */ |
|
2817 XMLPUBFUNEXPORT void |
|
2818 xmlSAX2InitDefaultSAXHandler(xmlSAXHandler* hdlr, int warning) |
|
2819 { |
|
2820 LOAD_GS_DIRECT |
|
2821 if ((hdlr == NULL) || (hdlr->initialized != 0)) |
|
2822 return; |
|
2823 |
|
2824 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue); |
|
2825 // Note: hdlr->warning is NULL after previous line |
|
2826 if(warning) |
|
2827 hdlr->warning = xmlParserWarning; |
|
2828 } |
|
2829 |
|
2830 /** |
|
2831 * xmlDefaultSAXHandlerInit: |
|
2832 * |
|
2833 * Initialize the default SAX2 handler |
|
2834 * |
|
2835 * OOM: never |
|
2836 */ |
|
2837 XMLPUBFUNEXPORT void |
|
2838 xmlDefaultSAXHandlerInit(void) |
|
2839 { |
|
2840 #ifdef XMLENGINE_SAX1 |
|
2841 #ifdef LIBXML_SAX1_ENABLED |
|
2842 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1); |
|
2843 #endif /* LIBXML_SAX1_ENABLED */ |
|
2844 #endif |
|
2845 } |
|
2846 |
|
2847 |
|
2848 #ifdef LIBXML_DOCB_ENABLED |
|
2849 |
|
2850 /** |
|
2851 * xmlSAX2InitDocbDefaultSAXHandler: |
|
2852 * @param hdlr the SAX handler |
|
2853 * |
|
2854 * Initialize the default DocBook SAX2 handler |
|
2855 */ |
|
2856 void |
|
2857 xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr) |
|
2858 { |
|
2859 if(hdlr->initialized != 0) |
|
2860 return; |
|
2861 |
|
2862 hdlr->internalSubset = xmlSAX2InternalSubset; |
|
2863 hdlr->externalSubset = NULL; |
|
2864 hdlr->isStandalone = xmlSAX2IsStandalone; |
|
2865 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset; |
|
2866 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset; |
|
2867 hdlr->resolveEntity = xmlSAX2ResolveEntity; |
|
2868 hdlr->getEntity = xmlSAX2GetEntity; |
|
2869 hdlr->getParameterEntity = NULL; |
|
2870 hdlr->entityDecl = xmlSAX2EntityDecl; |
|
2871 hdlr->attributeDecl = NULL; |
|
2872 hdlr->elementDecl = NULL; |
|
2873 hdlr->notationDecl = NULL; |
|
2874 hdlr->unparsedEntityDecl = NULL; |
|
2875 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator; |
|
2876 hdlr->startDocument = xmlSAX2StartDocument; |
|
2877 hdlr->endDocument = xmlSAX2EndDocument; |
|
2878 hdlr->startElement = xmlSAX2StartElement; |
|
2879 hdlr->endElement = xmlSAX2EndElement; |
|
2880 hdlr->reference = xmlSAX2Reference; |
|
2881 hdlr->characters = xmlSAX2Characters; |
|
2882 hdlr->cdataBlock = NULL; |
|
2883 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace; |
|
2884 hdlr->processingInstruction = NULL; |
|
2885 hdlr->comment = xmlSAX2Comment; |
|
2886 hdlr->warning = xmlParserWarning; |
|
2887 hdlr->error = xmlParserError; |
|
2888 hdlr->fatalError = xmlParserError; |
|
2889 |
|
2890 hdlr->initialized = 1; |
|
2891 } |
|
2892 |
|
2893 /** |
|
2894 * docbDefaultSAXHandlerInit: |
|
2895 * |
|
2896 * Initialize the default SAX handler |
|
2897 */ |
|
2898 void |
|
2899 docbDefaultSAXHandlerInit(void) |
|
2900 { |
|
2901 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler); |
|
2902 } |
|
2903 |
|
2904 #endif /* LIBXML_DOCB_ENABLED */ |
|
2905 |