blob: 0f261b7b3623bbf7ffd1437a0214c8f1221d95df [file] [log] [blame]
Daniel Veillard1af9a412003-08-20 22:54:39 +00001/*
2 * 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 */
8
9
10#define IN_LIBXML
11#include "libxml.h"
12#include <stdlib.h>
13#include <string.h>
Daniel Veillard1dc9feb2008-11-17 15:59:21 +000014#include <limits.h>
akirilov4e91cfd2018-06-01 13:46:04 -070015#include <stddef.h>
Daniel Veillard1af9a412003-08-20 22:54:39 +000016#include <libxml/xmlmemory.h>
17#include <libxml/tree.h>
18#include <libxml/parser.h>
19#include <libxml/parserInternals.h>
20#include <libxml/valid.h>
21#include <libxml/entities.h>
22#include <libxml/xmlerror.h>
23#include <libxml/debugXML.h>
24#include <libxml/xmlIO.h>
25#include <libxml/SAX.h>
26#include <libxml/uri.h>
27#include <libxml/valid.h>
28#include <libxml/HTMLtree.h>
29#include <libxml/globals.h>
30
Daniel Veillard1dc9feb2008-11-17 15:59:21 +000031/* Define SIZE_T_MAX unless defined through <limits.h>. */
32#ifndef SIZE_T_MAX
33# define SIZE_T_MAX ((size_t)-1)
34#endif /* !SIZE_T_MAX */
35
Daniel Veillard1af9a412003-08-20 22:54:39 +000036/* #define DEBUG_SAX2 */
37/* #define DEBUG_SAX2_TREE */
38
39/**
Daniel Veillarde57ec792003-09-10 10:50:59 +000040 * TODO:
41 *
42 * macro to flag unimplemented blocks
43 * XML_CATALOG_PREFER user env to select between system/public prefered
44 * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
45 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
46 *> values "system" and "public". I have made the default be "system" to
47 *> match yours.
48 */
Daniel Veillardf8e3db02012-09-11 13:26:36 +080049#define TODO \
Daniel Veillarde57ec792003-09-10 10:50:59 +000050 xmlGenericError(xmlGenericErrorContext, \
51 "Unimplemented block at %s:%d\n", \
52 __FILE__, __LINE__);
53
William M. Brack42331a92004-07-29 07:07:16 +000054/*
55 * xmlSAX2ErrMemory:
56 * @ctxt: an XML validation parser context
57 * @msg: a string to accompany the error message
58 */
David Kilzer4472c3a2016-05-13 15:13:17 +080059static void LIBXML_ATTR_FORMAT(2,0)
William M. Bracka3215c72004-07-31 16:24:01 +000060xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
Daniel Veillard740cb1a2012-07-18 16:05:37 +080061 xmlStructuredErrorFunc schannel = NULL;
62 const char *str1 = "out of memory\n";
63
Daniel Veillard34099b42004-11-04 17:34:35 +000064 if (ctxt != NULL) {
Daniel Veillard740cb1a2012-07-18 16:05:37 +080065 ctxt->errNo = XML_ERR_NO_MEMORY;
66 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
67 schannel = ctxt->sax->serror;
68 __xmlRaiseError(schannel,
69 ctxt->vctxt.error, ctxt->vctxt.userData,
70 ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
71 XML_ERR_ERROR, NULL, 0, (const char *) str1,
72 NULL, NULL, 0, 0,
73 msg, (const char *) str1, NULL);
Daniel Veillard34099b42004-11-04 17:34:35 +000074 ctxt->errNo = XML_ERR_NO_MEMORY;
75 ctxt->instate = XML_PARSER_EOF;
76 ctxt->disableSAX = 1;
Daniel Veillard740cb1a2012-07-18 16:05:37 +080077 } else {
78 __xmlRaiseError(schannel,
79 NULL, NULL,
80 ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
81 XML_ERR_ERROR, NULL, 0, (const char *) str1,
82 NULL, NULL, 0, 0,
83 msg, (const char *) str1, NULL);
Daniel Veillard34099b42004-11-04 17:34:35 +000084 }
William M. Brack42331a92004-07-29 07:07:16 +000085}
86
Daniel Veillarde57ec792003-09-10 10:50:59 +000087/**
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000088 * xmlValidError:
89 * @ctxt: an XML validation parser context
90 * @error: the error number
91 * @msg: the error message
92 * @str1: extra data
93 * @str2: extra data
94 *
95 * Handle a validation error
96 */
David Kilzer4472c3a2016-05-13 15:13:17 +080097static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillardf88d8cf2003-12-08 10:25:02 +000098xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
99 const char *msg, const char *str1, const char *str2)
100{
101 xmlStructuredErrorFunc schannel = NULL;
102
103 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
104 (ctxt->instate == XML_PARSER_EOF))
105 return;
Daniel Veillard34099b42004-11-04 17:34:35 +0000106 if (ctxt != NULL) {
107 ctxt->errNo = error;
108 if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
109 schannel = ctxt->sax->serror;
Daniel Veillard2728f842006-03-09 16:49:24 +0000110 __xmlRaiseError(schannel,
111 ctxt->vctxt.error, ctxt->vctxt.userData,
112 ctxt, NULL, XML_FROM_DTD, error,
113 XML_ERR_ERROR, NULL, 0, (const char *) str1,
114 (const char *) str2, NULL, 0, 0,
115 msg, (const char *) str1, (const char *) str2);
Daniel Veillard34099b42004-11-04 17:34:35 +0000116 ctxt->valid = 0;
Daniel Veillard2728f842006-03-09 16:49:24 +0000117 } else {
118 __xmlRaiseError(schannel,
119 NULL, NULL,
120 ctxt, NULL, XML_FROM_DTD, error,
121 XML_ERR_ERROR, NULL, 0, (const char *) str1,
122 (const char *) str2, NULL, 0, 0,
123 msg, (const char *) str1, (const char *) str2);
124 }
Daniel Veillardf88d8cf2003-12-08 10:25:02 +0000125}
126
127/**
Daniel Veillard87b30462005-07-05 14:04:36 +0000128 * xmlFatalErrMsg:
129 * @ctxt: an XML parser context
130 * @error: the error number
131 * @msg: the error message
132 * @str1: an error string
133 * @str2: an error string
134 *
135 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
136 */
David Kilzer4472c3a2016-05-13 15:13:17 +0800137static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillard87b30462005-07-05 14:04:36 +0000138xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
139 const char *msg, const xmlChar *str1, const xmlChar *str2)
140{
141 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
142 (ctxt->instate == XML_PARSER_EOF))
143 return;
144 if (ctxt != NULL)
145 ctxt->errNo = error;
146 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800147 XML_ERR_FATAL, NULL, 0,
Daniel Veillard87b30462005-07-05 14:04:36 +0000148 (const char *) str1, (const char *) str2,
149 NULL, 0, 0, msg, str1, str2);
150 if (ctxt != NULL) {
151 ctxt->wellFormed = 0;
152 ctxt->valid = 0;
153 if (ctxt->recovery == 0)
154 ctxt->disableSAX = 1;
155 }
156}
157
158/**
159 * xmlWarnMsg:
160 * @ctxt: an XML parser context
161 * @error: the error number
162 * @msg: the error message
163 * @str1: an error string
164 * @str2: an error string
165 *
166 * Handle a parser warning
167 */
David Kilzer4472c3a2016-05-13 15:13:17 +0800168static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillard87b30462005-07-05 14:04:36 +0000169xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
170 const char *msg, const xmlChar *str1)
171{
172 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
173 (ctxt->instate == XML_PARSER_EOF))
174 return;
175 if (ctxt != NULL)
176 ctxt->errNo = error;
177 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800178 XML_ERR_WARNING, NULL, 0,
Daniel Veillard87b30462005-07-05 14:04:36 +0000179 (const char *) str1, NULL,
180 NULL, 0, 0, msg, str1);
181}
182
183/**
184 * xmlNsErrMsg:
185 * @ctxt: an XML parser context
186 * @error: the error number
187 * @msg: the error message
188 * @str1: an error string
189 * @str2: an error string
190 *
191 * Handle a namespace error
192 */
David Kilzer4472c3a2016-05-13 15:13:17 +0800193static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillard87b30462005-07-05 14:04:36 +0000194xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
195 const char *msg, const xmlChar *str1, const xmlChar *str2)
196{
197 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
198 (ctxt->instate == XML_PARSER_EOF))
199 return;
200 if (ctxt != NULL)
201 ctxt->errNo = error;
202 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800203 XML_ERR_ERROR, NULL, 0,
Daniel Veillard87b30462005-07-05 14:04:36 +0000204 (const char *) str1, (const char *) str2,
205 NULL, 0, 0, msg, str1, str2);
206}
207
208/**
209 * xmlNsWarnMsg:
210 * @ctxt: an XML parser context
211 * @error: the error number
212 * @msg: the error message
213 * @str1: an error string
214 *
215 * Handle a namespace warning
216 */
David Kilzer4472c3a2016-05-13 15:13:17 +0800217static void LIBXML_ATTR_FORMAT(3,0)
Daniel Veillard87b30462005-07-05 14:04:36 +0000218xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
219 const char *msg, const xmlChar *str1, const xmlChar *str2)
220{
221 if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
222 (ctxt->instate == XML_PARSER_EOF))
223 return;
224 if (ctxt != NULL)
225 ctxt->errNo = error;
226 __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800227 XML_ERR_WARNING, NULL, 0,
Daniel Veillard87b30462005-07-05 14:04:36 +0000228 (const char *) str1, (const char *) str2,
229 NULL, 0, 0, msg, str1, str2);
230}
231
232/**
Daniel Veillard1af9a412003-08-20 22:54:39 +0000233 * xmlSAX2GetPublicId:
234 * @ctx: the user data (XML parser context)
235 *
236 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
237 *
238 * Returns a xmlChar *
239 */
240const xmlChar *
241xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
242{
243 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
244 return(NULL);
245}
246
247/**
248 * xmlSAX2GetSystemId:
249 * @ctx: the user data (XML parser context)
250 *
251 * Provides the system ID, basically URL or filename e.g.
252 * http://www.sgmlsource.com/dtds/memo.dtd
253 *
254 * Returns a xmlChar *
255 */
256const xmlChar *
257xmlSAX2GetSystemId(void *ctx)
258{
259 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard24505b02005-07-28 23:49:35 +0000260 if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800261 return((const xmlChar *) ctxt->input->filename);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000262}
263
264/**
265 * xmlSAX2GetLineNumber:
266 * @ctx: the user data (XML parser context)
267 *
268 * Provide the line number of the current parsing point.
269 *
270 * Returns an int
271 */
272int
273xmlSAX2GetLineNumber(void *ctx)
274{
275 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000276 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000277 return(ctxt->input->line);
278}
279
280/**
281 * xmlSAX2GetColumnNumber:
282 * @ctx: the user data (XML parser context)
283 *
284 * Provide the column number of the current parsing point.
285 *
286 * Returns an int
287 */
288int
289xmlSAX2GetColumnNumber(void *ctx)
290{
291 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000292 if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000293 return(ctxt->input->col);
294}
295
296/**
297 * xmlSAX2IsStandalone:
298 * @ctx: the user data (XML parser context)
299 *
300 * Is this document tagged standalone ?
301 *
302 * Returns 1 if true
303 */
304int
305xmlSAX2IsStandalone(void *ctx)
306{
307 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000308 if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000309 return(ctxt->myDoc->standalone == 1);
310}
311
312/**
313 * xmlSAX2HasInternalSubset:
314 * @ctx: the user data (XML parser context)
315 *
316 * Does this document has an internal subset
317 *
318 * Returns 1 if true
319 */
320int
321xmlSAX2HasInternalSubset(void *ctx)
322{
323 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000324 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000325 return(ctxt->myDoc->intSubset != NULL);
326}
327
328/**
329 * xmlSAX2HasExternalSubset:
330 * @ctx: the user data (XML parser context)
331 *
332 * Does this document has an external subset
333 *
334 * Returns 1 if true
335 */
336int
337xmlSAX2HasExternalSubset(void *ctx)
338{
339 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +0000340 if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000341 return(ctxt->myDoc->extSubset != NULL);
342}
343
344/**
345 * xmlSAX2InternalSubset:
346 * @ctx: the user data (XML parser context)
347 * @name: the root element name
348 * @ExternalID: the external ID
349 * @SystemID: the SYSTEM ID (e.g. filename or URL)
350 *
351 * Callback on internal subset declaration.
352 */
353void
354xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
355 const xmlChar *ExternalID, const xmlChar *SystemID)
356{
357 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
358 xmlDtdPtr dtd;
Daniel Veillard34099b42004-11-04 17:34:35 +0000359 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000360#ifdef DEBUG_SAX
361 xmlGenericError(xmlGenericErrorContext,
362 "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
363 name, ExternalID, SystemID);
364#endif
365
366 if (ctxt->myDoc == NULL)
367 return;
368 dtd = xmlGetIntSubset(ctxt->myDoc);
369 if (dtd != NULL) {
370 if (ctxt->html)
371 return;
372 xmlUnlinkNode((xmlNodePtr) dtd);
373 xmlFreeDtd(dtd);
374 ctxt->myDoc->intSubset = NULL;
375 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800376 ctxt->myDoc->intSubset =
Daniel Veillard1af9a412003-08-20 22:54:39 +0000377 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
William M. Brack42331a92004-07-29 07:07:16 +0000378 if (ctxt->myDoc->intSubset == NULL)
379 xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000380}
381
382/**
383 * xmlSAX2ExternalSubset:
384 * @ctx: the user data (XML parser context)
385 * @name: the root element name
386 * @ExternalID: the external ID
387 * @SystemID: the SYSTEM ID (e.g. filename or URL)
388 *
389 * Callback on external subset declaration.
390 */
391void
392xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
393 const xmlChar *ExternalID, const xmlChar *SystemID)
394{
395 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000396 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000397#ifdef DEBUG_SAX
398 xmlGenericError(xmlGenericErrorContext,
399 "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
400 name, ExternalID, SystemID);
401#endif
402 if (((ExternalID != NULL) || (SystemID != NULL)) &&
403 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
404 (ctxt->wellFormed && ctxt->myDoc))) {
405 /*
406 * Try to fetch and parse the external subset.
407 */
408 xmlParserInputPtr oldinput;
409 int oldinputNr;
410 int oldinputMax;
411 xmlParserInputPtr *oldinputTab;
412 xmlParserInputPtr input = NULL;
413 xmlCharEncoding enc;
414 int oldcharset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800415 const xmlChar *oldencoding;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000416
417 /*
418 * Ask the Entity resolver to load the damn thing
419 */
420 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
421 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
422 SystemID);
423 if (input == NULL) {
424 return;
425 }
426
427 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
428
429 /*
430 * make sure we won't destroy the main document context
431 */
432 oldinput = ctxt->input;
433 oldinputNr = ctxt->inputNr;
434 oldinputMax = ctxt->inputMax;
435 oldinputTab = ctxt->inputTab;
436 oldcharset = ctxt->charset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800437 oldencoding = ctxt->encoding;
438 ctxt->encoding = NULL;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000439
440 ctxt->inputTab = (xmlParserInputPtr *)
441 xmlMalloc(5 * sizeof(xmlParserInputPtr));
442 if (ctxt->inputTab == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000443 xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
Daniel Veillard1af9a412003-08-20 22:54:39 +0000444 ctxt->input = oldinput;
445 ctxt->inputNr = oldinputNr;
446 ctxt->inputMax = oldinputMax;
447 ctxt->inputTab = oldinputTab;
448 ctxt->charset = oldcharset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800449 ctxt->encoding = oldencoding;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000450 return;
451 }
452 ctxt->inputNr = 0;
453 ctxt->inputMax = 5;
454 ctxt->input = NULL;
455 xmlPushInput(ctxt, input);
456
457 /*
458 * On the fly encoding conversion if needed
459 */
460 if (ctxt->input->length >= 4) {
461 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
462 xmlSwitchEncoding(ctxt, enc);
463 }
464
465 if (input->filename == NULL)
466 input->filename = (char *) xmlCanonicPath(SystemID);
467 input->line = 1;
468 input->col = 1;
469 input->base = ctxt->input->cur;
470 input->cur = ctxt->input->cur;
471 input->free = NULL;
472
473 /*
474 * let's parse that entity knowing it's an external subset.
475 */
476 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
477
478 /*
479 * Free up the external entities
480 */
481
482 while (ctxt->inputNr > 1)
483 xmlPopInput(ctxt);
484 xmlFreeInputStream(ctxt->input);
485 xmlFree(ctxt->inputTab);
486
487 /*
488 * Restore the parsing context of the main entity
489 */
490 ctxt->input = oldinput;
491 ctxt->inputNr = oldinputNr;
492 ctxt->inputMax = oldinputMax;
493 ctxt->inputTab = oldinputTab;
494 ctxt->charset = oldcharset;
Daniel Veillardab0e3502013-03-27 13:21:38 +0800495 if ((ctxt->encoding != NULL) &&
496 ((ctxt->dict == NULL) ||
497 (!xmlDictOwns(ctxt->dict, ctxt->encoding))))
498 xmlFree((xmlChar *) ctxt->encoding);
499 ctxt->encoding = oldencoding;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000500 /* ctxt->wellFormed = oldwellFormed; */
501 }
502}
503
504/**
505 * xmlSAX2ResolveEntity:
506 * @ctx: the user data (XML parser context)
507 * @publicId: The public ID of the entity
508 * @systemId: The system ID of the entity
509 *
510 * The entity loader, to control the loading of external entities,
511 * the application can either:
512 * - override this xmlSAX2ResolveEntity() callback in the SAX block
513 * - or better use the xmlSetExternalEntityLoader() function to
514 * set up it's own entity resolution routine
515 *
516 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
517 */
518xmlParserInputPtr
519xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
520{
521 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
522 xmlParserInputPtr ret;
523 xmlChar *URI;
524 const char *base = NULL;
525
Daniel Veillard34099b42004-11-04 17:34:35 +0000526 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000527 if (ctxt->input != NULL)
528 base = ctxt->input->filename;
529 if (base == NULL)
530 base = ctxt->directory;
531
532 URI = xmlBuildURI(systemId, (const xmlChar *) base);
533
534#ifdef DEBUG_SAX
535 xmlGenericError(xmlGenericErrorContext,
536 "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
537#endif
538
539 ret = xmlLoadExternalEntity((const char *) URI,
540 (const char *) publicId, ctxt);
541 if (URI != NULL)
542 xmlFree(URI);
543 return(ret);
544}
545
546/**
547 * xmlSAX2GetEntity:
548 * @ctx: the user data (XML parser context)
549 * @name: The entity name
550 *
551 * Get an entity by name
552 *
553 * Returns the xmlEntityPtr if found.
554 */
555xmlEntityPtr
556xmlSAX2GetEntity(void *ctx, const xmlChar *name)
557{
558 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
559 xmlEntityPtr ret = NULL;
560
Daniel Veillard34099b42004-11-04 17:34:35 +0000561 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000562#ifdef DEBUG_SAX
563 xmlGenericError(xmlGenericErrorContext,
564 "SAX.xmlSAX2GetEntity(%s)\n", name);
565#endif
566
567 if (ctxt->inSubset == 0) {
568 ret = xmlGetPredefinedEntity(name);
569 if (ret != NULL)
570 return(ret);
571 }
572 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
573 if (ctxt->inSubset == 2) {
574 ctxt->myDoc->standalone = 0;
575 ret = xmlGetDocEntity(ctxt->myDoc, name);
576 ctxt->myDoc->standalone = 1;
577 } else {
578 ret = xmlGetDocEntity(ctxt->myDoc, name);
579 if (ret == NULL) {
580 ctxt->myDoc->standalone = 0;
581 ret = xmlGetDocEntity(ctxt->myDoc, name);
582 if (ret != NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +0000583 xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
584 "Entity(%s) document marked standalone but requires external subset\n",
585 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000586 }
587 ctxt->myDoc->standalone = 1;
588 }
589 }
590 } else {
591 ret = xmlGetDocEntity(ctxt->myDoc, name);
592 }
593 if ((ret != NULL) &&
594 ((ctxt->validate) || (ctxt->replaceEntities)) &&
595 (ret->children == NULL) &&
596 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
597 int val;
598
599 /*
600 * for validation purposes we really need to fetch and
601 * parse the external entity
602 */
603 xmlNodePtr children;
Daniel Veillarda3f1e3e2013-03-11 13:57:53 +0800604 unsigned long oldnbent = ctxt->nbentities;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000605
606 val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
607 ret->ExternalID, &children);
608 if (val == 0) {
609 xmlAddChildList((xmlNodePtr) ret, children);
610 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000611 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
612 "Failure to process entity %s\n", name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000613 ctxt->validate = 0;
614 return(NULL);
615 }
616 ret->owner = 1;
Daniel Veillarda3f1e3e2013-03-11 13:57:53 +0800617 if (ret->checked == 0) {
Daniel Veillardcff25462013-03-11 15:57:55 +0800618 ret->checked = (ctxt->nbentities - oldnbent + 1) * 2;
619 if ((ret->content != NULL) && (xmlStrchr(ret->content, '<')))
620 ret->checked |= 1;
Daniel Veillarda3f1e3e2013-03-11 13:57:53 +0800621 }
Daniel Veillard1af9a412003-08-20 22:54:39 +0000622 }
623 return(ret);
624}
625
626/**
627 * xmlSAX2GetParameterEntity:
628 * @ctx: the user data (XML parser context)
629 * @name: The entity name
630 *
631 * Get a parameter entity by name
632 *
633 * Returns the xmlEntityPtr if found.
634 */
635xmlEntityPtr
636xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
637{
638 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
639 xmlEntityPtr ret;
640
Daniel Veillard34099b42004-11-04 17:34:35 +0000641 if (ctx == NULL) return(NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000642#ifdef DEBUG_SAX
643 xmlGenericError(xmlGenericErrorContext,
644 "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
645#endif
646
647 ret = xmlGetParameterEntity(ctxt->myDoc, name);
648 return(ret);
649}
650
651
652/**
653 * xmlSAX2EntityDecl:
654 * @ctx: the user data (XML parser context)
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800655 * @name: the entity name
656 * @type: the entity type
Daniel Veillard1af9a412003-08-20 22:54:39 +0000657 * @publicId: The public ID of the entity
658 * @systemId: The system ID of the entity
659 * @content: the entity value (without processing).
660 *
661 * An entity definition has been parsed
662 */
663void
664xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
665 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
666{
667 xmlEntityPtr ent;
668 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
669
Daniel Veillard34099b42004-11-04 17:34:35 +0000670 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000671#ifdef DEBUG_SAX
672 xmlGenericError(xmlGenericErrorContext,
673 "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
674 name, type, publicId, systemId, content);
675#endif
676 if (ctxt->inSubset == 1) {
677 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
678 systemId, content);
Daniel Veillard87b30462005-07-05 14:04:36 +0000679 if ((ent == NULL) && (ctxt->pedantic))
680 xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
681 "Entity(%s) already defined in the internal subset\n",
682 name);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000683 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
684 xmlChar *URI;
685 const char *base = NULL;
686
687 if (ctxt->input != NULL)
688 base = ctxt->input->filename;
689 if (base == NULL)
690 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800691
Daniel Veillard1af9a412003-08-20 22:54:39 +0000692 URI = xmlBuildURI(systemId, (const xmlChar *) base);
693 ent->URI = URI;
694 }
695 } else if (ctxt->inSubset == 2) {
696 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
697 systemId, content);
698 if ((ent == NULL) && (ctxt->pedantic) &&
699 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800700 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000701 "Entity(%s) already defined in the external subset\n", name);
702 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
703 xmlChar *URI;
704 const char *base = NULL;
705
706 if (ctxt->input != NULL)
707 base = ctxt->input->filename;
708 if (base == NULL)
709 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800710
Daniel Veillard1af9a412003-08-20 22:54:39 +0000711 URI = xmlBuildURI(systemId, (const xmlChar *) base);
712 ent->URI = URI;
713 }
714 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000715 xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
716 "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
717 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000718 }
719}
720
721/**
722 * xmlSAX2AttributeDecl:
723 * @ctx: the user data (XML parser context)
724 * @elem: the name of the element
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800725 * @fullname: the attribute name
726 * @type: the attribute type
Daniel Veillard1af9a412003-08-20 22:54:39 +0000727 * @def: the type of default value
728 * @defaultValue: the attribute default value
729 * @tree: the tree of enumerated value set
730 *
731 * An attribute definition has been parsed
732 */
733void
734xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
735 int type, int def, const xmlChar *defaultValue,
736 xmlEnumerationPtr tree)
737{
738 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
739 xmlAttributePtr attr;
740 xmlChar *name = NULL, *prefix = NULL;
741
Daniel Veillard2728f842006-03-09 16:49:24 +0000742 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
743 return;
744
Daniel Veillard1af9a412003-08-20 22:54:39 +0000745#ifdef DEBUG_SAX
746 xmlGenericError(xmlGenericErrorContext,
747 "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
748 elem, fullname, type, def, defaultValue);
749#endif
Daniel Veillard68cb4b22004-04-18 20:55:39 +0000750 if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
751 (type != XML_ATTRIBUTE_ID)) {
752 /*
753 * Raise the error but keep the validity flag
754 */
755 int tmp = ctxt->valid;
756 xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
757 "xml:id : attribute type should be ID\n", NULL, NULL);
758 ctxt->valid = tmp;
759 }
Daniel Veillarde57ec792003-09-10 10:50:59 +0000760 /* TODO: optimize name/prefix allocation */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000761 name = xmlSplitQName(ctxt, fullname, &prefix);
762 ctxt->vctxt.valid = 1;
763 if (ctxt->inSubset == 1)
764 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
765 name, prefix, (xmlAttributeType) type,
766 (xmlAttributeDefault) def, defaultValue, tree);
767 else if (ctxt->inSubset == 2)
768 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800769 name, prefix, (xmlAttributeType) type,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000770 (xmlAttributeDefault) def, defaultValue, tree);
771 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000772 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
773 "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
774 name, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +0000775 xmlFreeEnumeration(tree);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000776 return;
777 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000778#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000779 if (ctxt->vctxt.valid == 0)
780 ctxt->valid = 0;
781 if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
Daniel Veillard2728f842006-03-09 16:49:24 +0000782 (ctxt->myDoc->intSubset != NULL))
Daniel Veillard1af9a412003-08-20 22:54:39 +0000783 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
784 attr);
Daniel Veillard4432df22003-09-28 18:58:27 +0000785#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000786 if (prefix != NULL)
787 xmlFree(prefix);
788 if (name != NULL)
789 xmlFree(name);
790}
791
792/**
793 * xmlSAX2ElementDecl:
794 * @ctx: the user data (XML parser context)
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800795 * @name: the element name
796 * @type: the element type
Daniel Veillard1af9a412003-08-20 22:54:39 +0000797 * @content: the element value tree
798 *
799 * An element definition has been parsed
800 */
801void
802xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
803 xmlElementContentPtr content)
804{
805 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
806 xmlElementPtr elem = NULL;
807
Daniel Veillard2728f842006-03-09 16:49:24 +0000808 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
809 return;
810
Daniel Veillard1af9a412003-08-20 22:54:39 +0000811#ifdef DEBUG_SAX
812 xmlGenericError(xmlGenericErrorContext,
813 "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
814#endif
815
816 if (ctxt->inSubset == 1)
817 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
818 name, (xmlElementTypeVal) type, content);
819 else if (ctxt->inSubset == 2)
820 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
821 name, (xmlElementTypeVal) type, content);
822 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000823 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
824 "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
825 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000826 return;
827 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000828#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000829 if (elem == NULL)
830 ctxt->valid = 0;
831 if (ctxt->validate && ctxt->wellFormed &&
832 ctxt->myDoc && ctxt->myDoc->intSubset)
833 ctxt->valid &=
834 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard4432df22003-09-28 18:58:27 +0000835#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000836}
837
838/**
839 * xmlSAX2NotationDecl:
840 * @ctx: the user data (XML parser context)
841 * @name: The name of the notation
842 * @publicId: The public ID of the entity
843 * @systemId: The system ID of the entity
844 *
845 * What to do when a notation declaration has been parsed.
846 */
847void
848xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
849 const xmlChar *publicId, const xmlChar *systemId)
850{
851 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
852 xmlNotationPtr nota = NULL;
853
Daniel Veillard2728f842006-03-09 16:49:24 +0000854 if ((ctxt == NULL) || (ctxt->myDoc == NULL))
855 return;
856
Daniel Veillard1af9a412003-08-20 22:54:39 +0000857#ifdef DEBUG_SAX
858 xmlGenericError(xmlGenericErrorContext,
859 "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
860#endif
861
862 if ((publicId == NULL) && (systemId == NULL)) {
Daniel Veillard87b30462005-07-05 14:04:36 +0000863 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
864 "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
865 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000866 return;
867 } else if (ctxt->inSubset == 1)
868 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
869 publicId, systemId);
870 else if (ctxt->inSubset == 2)
871 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
872 publicId, systemId);
873 else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000874 xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
875 "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
876 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000877 return;
878 }
Daniel Veillard4432df22003-09-28 18:58:27 +0000879#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +0000880 if (nota == NULL) ctxt->valid = 0;
Daniel Veillard2728f842006-03-09 16:49:24 +0000881 if ((ctxt->validate) && (ctxt->wellFormed) &&
882 (ctxt->myDoc->intSubset != NULL))
Daniel Veillard1af9a412003-08-20 22:54:39 +0000883 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
884 nota);
Daniel Veillard4432df22003-09-28 18:58:27 +0000885#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +0000886}
887
888/**
889 * xmlSAX2UnparsedEntityDecl:
890 * @ctx: the user data (XML parser context)
891 * @name: The name of the entity
892 * @publicId: The public ID of the entity
893 * @systemId: The system ID of the entity
894 * @notationName: the name of the notation
895 *
896 * What to do when an unparsed entity declaration is parsed
897 */
898void
899xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
900 const xmlChar *publicId, const xmlChar *systemId,
901 const xmlChar *notationName)
902{
903 xmlEntityPtr ent;
904 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard34099b42004-11-04 17:34:35 +0000905 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +0000906#ifdef DEBUG_SAX
907 xmlGenericError(xmlGenericErrorContext,
908 "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
909 name, publicId, systemId, notationName);
910#endif
911 if (ctxt->inSubset == 1) {
912 ent = xmlAddDocEntity(ctxt->myDoc, name,
913 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
914 publicId, systemId, notationName);
915 if ((ent == NULL) && (ctxt->pedantic) &&
916 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800917 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000918 "Entity(%s) already defined in the internal subset\n", name);
919 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
920 xmlChar *URI;
921 const char *base = NULL;
922
923 if (ctxt->input != NULL)
924 base = ctxt->input->filename;
925 if (base == NULL)
926 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800927
Daniel Veillard1af9a412003-08-20 22:54:39 +0000928 URI = xmlBuildURI(systemId, (const xmlChar *) base);
929 ent->URI = URI;
930 }
931 } else if (ctxt->inSubset == 2) {
932 ent = xmlAddDtdEntity(ctxt->myDoc, name,
933 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
934 publicId, systemId, notationName);
935 if ((ent == NULL) && (ctxt->pedantic) &&
936 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800937 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +0000938 "Entity(%s) already defined in the external subset\n", name);
939 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
940 xmlChar *URI;
941 const char *base = NULL;
942
943 if (ctxt->input != NULL)
944 base = ctxt->input->filename;
945 if (base == NULL)
946 base = ctxt->directory;
Daniel Veillardf8e3db02012-09-11 13:26:36 +0800947
Daniel Veillard1af9a412003-08-20 22:54:39 +0000948 URI = xmlBuildURI(systemId, (const xmlChar *) base);
949 ent->URI = URI;
950 }
951 } else {
Daniel Veillard87b30462005-07-05 14:04:36 +0000952 xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
953 "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
954 name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +0000955 }
956}
957
958/**
959 * xmlSAX2SetDocumentLocator:
960 * @ctx: the user data (XML parser context)
961 * @loc: A SAX Locator
962 *
963 * Receive the document locator at startup, actually xmlDefaultSAXLocator
964 * Everything is available on the context, so this is useless in our case.
965 */
966void
967xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
968{
969 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
970#ifdef DEBUG_SAX
971 xmlGenericError(xmlGenericErrorContext,
972 "SAX.xmlSAX2SetDocumentLocator()\n");
973#endif
974}
975
976/**
977 * xmlSAX2StartDocument:
978 * @ctx: the user data (XML parser context)
979 *
980 * called when the document start being processed.
981 */
982void
983xmlSAX2StartDocument(void *ctx)
984{
985 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
986 xmlDocPtr doc;
987
Daniel Veillard34099b42004-11-04 17:34:35 +0000988 if (ctx == NULL) return;
989
Daniel Veillard1af9a412003-08-20 22:54:39 +0000990#ifdef DEBUG_SAX
991 xmlGenericError(xmlGenericErrorContext,
992 "SAX.xmlSAX2StartDocument()\n");
993#endif
994 if (ctxt->html) {
995#ifdef LIBXML_HTML_ENABLED
996 if (ctxt->myDoc == NULL)
997 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
998 if (ctxt->myDoc == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +0000999 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001000 return;
1001 }
Gaurava885f132013-08-03 22:16:02 +08001002 ctxt->myDoc->properties = XML_DOC_HTML;
1003 ctxt->myDoc->parseFlags = ctxt->options;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001004#else
1005 xmlGenericError(xmlGenericErrorContext,
1006 "libxml2 built without HTML support\n");
1007 ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1008 ctxt->instate = XML_PARSER_EOF;
1009 ctxt->disableSAX = 1;
1010 return;
1011#endif
1012 } else {
1013 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
1014 if (doc != NULL) {
Daniel Veillardae0765b2008-07-31 19:54:59 +00001015 doc->properties = 0;
1016 if (ctxt->options & XML_PARSE_OLD10)
1017 doc->properties |= XML_DOC_OLD10;
1018 doc->parseFlags = ctxt->options;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001019 if (ctxt->encoding != NULL)
1020 doc->encoding = xmlStrdup(ctxt->encoding);
1021 else
1022 doc->encoding = NULL;
1023 doc->standalone = ctxt->standalone;
1024 } else {
William M. Brack42331a92004-07-29 07:07:16 +00001025 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001026 return;
1027 }
Daniel Veillard500a1de2004-03-22 15:22:58 +00001028 if ((ctxt->dictNames) && (doc != NULL)) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001029 doc->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00001030 xmlDictReference(doc->dict);
1031 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001032 }
1033 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
1034 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
Daniel Veillardb8efdda2006-10-10 12:37:14 +00001035 ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001036 if (ctxt->myDoc->URL == NULL)
William M. Bracka3215c72004-07-31 16:24:01 +00001037 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001038 }
1039}
1040
1041/**
1042 * xmlSAX2EndDocument:
1043 * @ctx: the user data (XML parser context)
1044 *
1045 * called when the document end has been detected.
1046 */
1047void
1048xmlSAX2EndDocument(void *ctx)
1049{
1050 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1051#ifdef DEBUG_SAX
1052 xmlGenericError(xmlGenericErrorContext,
1053 "SAX.xmlSAX2EndDocument()\n");
1054#endif
Daniel Veillard34099b42004-11-04 17:34:35 +00001055 if (ctx == NULL) return;
Daniel Veillard4432df22003-09-28 18:58:27 +00001056#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001057 if (ctxt->validate && ctxt->wellFormed &&
1058 ctxt->myDoc && ctxt->myDoc->intSubset)
1059 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard4432df22003-09-28 18:58:27 +00001060#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001061
1062 /*
1063 * Grab the encoding if it was added on-the-fly
1064 */
1065 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
1066 (ctxt->myDoc->encoding == NULL)) {
1067 ctxt->myDoc->encoding = ctxt->encoding;
1068 ctxt->encoding = NULL;
1069 }
Daniel Veillard36e5cd52004-11-02 14:52:23 +00001070 if ((ctxt->inputTab != NULL) &&
1071 (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
1072 (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001073 (ctxt->myDoc->encoding == NULL)) {
1074 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
1075 }
1076 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
1077 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
1078 ctxt->myDoc->charset = ctxt->charset;
1079 }
1080}
1081
Nicolas Le Cam77b5b462014-02-10 10:32:45 +08001082#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001083/**
1084 * xmlSAX2AttributeInternal:
1085 * @ctx: the user data (XML parser context)
1086 * @fullname: The attribute name, including namespace prefix
1087 * @value: The attribute value
1088 * @prefix: the prefix on the element node
1089 *
1090 * Handle an attribute that has been read by the parser.
1091 * The default handling is to convert the attribute into an
1092 * DOM subtree and past it in a new xmlAttr element added to
1093 * the element.
1094 */
1095static void
1096xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00001097 const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001098{
1099 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1100 xmlAttrPtr ret;
1101 xmlChar *name;
1102 xmlChar *ns;
1103 xmlChar *nval;
1104 xmlNsPtr namespace;
1105
Daniel Veillarddbbd72b2007-06-12 15:15:52 +00001106 if (ctxt->html) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001107 name = xmlStrdup(fullname);
Daniel Veillarddbbd72b2007-06-12 15:15:52 +00001108 ns = NULL;
1109 namespace = NULL;
1110 } else {
1111 /*
1112 * Split the full name into a namespace prefix and the tag name
1113 */
1114 name = xmlSplitQName(ctxt, fullname, &ns);
1115 if ((name != NULL) && (name[0] == 0)) {
1116 if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
1117 xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
1118 "invalid namespace declaration '%s'\n",
1119 fullname, NULL);
1120 } else {
1121 xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
1122 "Avoid attribute ending with ':' like '%s'\n",
1123 fullname, NULL);
1124 }
1125 if (ns != NULL)
1126 xmlFree(ns);
1127 ns = NULL;
1128 xmlFree(name);
1129 name = xmlStrdup(fullname);
1130 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001131 }
1132 if (name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001133 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001134 if (ns != NULL)
1135 xmlFree(ns);
1136 return;
1137 }
1138
Daniel Veillard3c080d62010-03-15 15:47:50 +01001139#ifdef LIBXML_HTML_ENABLED
1140 if ((ctxt->html) &&
1141 (value == NULL) && (htmlIsBooleanAttr(fullname))) {
Daniel Veillard06c93b72010-03-15 16:08:44 +01001142 nval = xmlStrdup(fullname);
1143 value = (const xmlChar *) nval;
Daniel Veillard3c080d62010-03-15 15:47:50 +01001144 } else
1145#endif
1146 {
Daniel Veillard4432df22003-09-28 18:58:27 +00001147#ifdef LIBXML_VALID_ENABLED
Daniel Veillard3c080d62010-03-15 15:47:50 +01001148 /*
1149 * Do the last stage of the attribute normalization
1150 * Needed for HTML too:
1151 * http://www.w3.org/TR/html4/types.html#h-6.2
1152 */
1153 ctxt->vctxt.valid = 1;
1154 nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
1155 ctxt->myDoc, ctxt->node,
1156 fullname, value);
1157 if (ctxt->vctxt.valid != 1) {
1158 ctxt->valid = 0;
1159 }
1160 if (nval != NULL)
1161 value = nval;
Daniel Veillard4432df22003-09-28 18:58:27 +00001162#else
Daniel Veillard3c080d62010-03-15 15:47:50 +01001163 nval = NULL;
Daniel Veillard4432df22003-09-28 18:58:27 +00001164#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard3c080d62010-03-15 15:47:50 +01001165 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001166
1167 /*
1168 * Check whether it's a namespace definition
1169 */
1170 if ((!ctxt->html) && (ns == NULL) &&
1171 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1172 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1173 xmlNsPtr nsret;
1174 xmlChar *val;
1175
1176 if (!ctxt->replaceEntities) {
1177 ctxt->depth++;
1178 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1179 0,0,0);
1180 ctxt->depth--;
Gaurav3e0eec42014-06-13 14:45:20 +08001181 if (val == NULL) {
1182 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1183 if (name != NULL)
1184 xmlFree(name);
akirilov4e91cfd2018-06-01 13:46:04 -07001185 if (nval != NULL)
1186 xmlFree(nval);
Gaurav3e0eec42014-06-13 14:45:20 +08001187 return;
1188 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001189 } else {
1190 val = (xmlChar *) value;
1191 }
1192
1193 if (val[0] != 0) {
1194 xmlURIPtr uri;
1195
1196 uri = xmlParseURI((const char *)val);
1197 if (uri == NULL) {
1198 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001199 ctxt->sax->warning(ctxt->userData,
William M. Brack4811ba32003-09-06 18:02:53 +00001200 "xmlns: %s not a valid URI\n", val);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001201 } else {
1202 if (uri->scheme == NULL) {
1203 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001204 ctxt->sax->warning(ctxt->userData,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001205 "xmlns: URI %s is not absolute\n", val);
1206 }
1207 xmlFreeURI(uri);
1208 }
1209 }
1210
1211 /* a default namespace definition */
1212 nsret = xmlNewNs(ctxt->node, val, NULL);
1213
Daniel Veillard4432df22003-09-28 18:58:27 +00001214#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001215 /*
1216 * Validate also for namespace decls, they are attributes from
1217 * an XML-1.0 perspective
1218 */
1219 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1220 ctxt->myDoc && ctxt->myDoc->intSubset)
1221 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1222 ctxt->node, prefix, nsret, val);
Daniel Veillard4432df22003-09-28 18:58:27 +00001223#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001224 if (name != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001225 xmlFree(name);
1226 if (nval != NULL)
1227 xmlFree(nval);
1228 if (val != value)
1229 xmlFree(val);
1230 return;
1231 }
1232 if ((!ctxt->html) &&
1233 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1234 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1235 xmlNsPtr nsret;
1236 xmlChar *val;
1237
1238 if (!ctxt->replaceEntities) {
1239 ctxt->depth++;
1240 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1241 0,0,0);
1242 ctxt->depth--;
1243 if (val == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001244 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001245 xmlFree(ns);
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001246 if (name != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001247 xmlFree(name);
akirilov4e91cfd2018-06-01 13:46:04 -07001248 if (nval != NULL)
1249 xmlFree(nval);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001250 return;
1251 }
1252 } else {
1253 val = (xmlChar *) value;
1254 }
1255
1256 if (val[0] == 0) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001257 xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1258 "Empty namespace name for prefix %s\n", name, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001259 }
1260 if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1261 xmlURIPtr uri;
1262
1263 uri = xmlParseURI((const char *)val);
1264 if (uri == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001265 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001266 "xmlns:%s: %s not a valid URI\n", name, value);
1267 } else {
1268 if (uri->scheme == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001269 xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001270 "xmlns:%s: URI %s is not absolute\n", name, value);
1271 }
1272 xmlFreeURI(uri);
1273 }
1274 }
1275
1276 /* a standard namespace definition */
1277 nsret = xmlNewNs(ctxt->node, val, name);
1278 xmlFree(ns);
Daniel Veillard4432df22003-09-28 18:58:27 +00001279#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001280 /*
1281 * Validate also for namespace decls, they are attributes from
1282 * an XML-1.0 perspective
1283 */
1284 if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1285 ctxt->myDoc && ctxt->myDoc->intSubset)
1286 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1287 ctxt->node, prefix, nsret, value);
Daniel Veillard4432df22003-09-28 18:58:27 +00001288#endif /* LIBXML_VALID_ENABLED */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001289 if (name != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001290 xmlFree(name);
1291 if (nval != NULL)
1292 xmlFree(nval);
1293 if (val != value)
1294 xmlFree(val);
1295 return;
1296 }
1297
1298 if (ns != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001299 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
Daniel Veillardd44b9362009-09-07 12:15:08 +02001300
Daniel Veillard67906942003-08-28 21:13:25 +00001301 if (namespace == NULL) {
Daniel Veillard87b30462005-07-05 14:04:36 +00001302 xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
William M. Brack4811ba32003-09-06 18:02:53 +00001303 "Namespace prefix %s of attribute %s is not defined\n",
Daniel Veillard67906942003-08-28 21:13:25 +00001304 ns, name);
Daniel Veillardd44b9362009-09-07 12:15:08 +02001305 } else {
1306 xmlAttrPtr prop;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001307
Daniel Veillardd44b9362009-09-07 12:15:08 +02001308 prop = ctxt->node->properties;
1309 while (prop != NULL) {
1310 if (prop->ns != NULL) {
1311 if ((xmlStrEqual(name, prop->name)) &&
1312 ((namespace == prop->ns) ||
1313 (xmlStrEqual(namespace->href, prop->ns->href)))) {
1314 xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
1315 "Attribute %s in %s redefined\n",
1316 name, namespace->href);
1317 ctxt->wellFormed = 0;
1318 if (ctxt->recovery == 0) ctxt->disableSAX = 1;
akirilov4e91cfd2018-06-01 13:46:04 -07001319 if (name != NULL)
1320 xmlFree(name);
Daniel Veillardd44b9362009-09-07 12:15:08 +02001321 goto error;
1322 }
1323 }
1324 prop = prop->next;
1325 }
1326 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001327 } else {
1328 namespace = NULL;
1329 }
1330
1331 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1332 ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1333
1334 if (ret != NULL) {
1335 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1336 xmlNodePtr tmp;
1337
1338 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1339 tmp = ret->children;
1340 while (tmp != NULL) {
1341 tmp->parent = (xmlNodePtr) ret;
1342 if (tmp->next == NULL)
1343 ret->last = tmp;
1344 tmp = tmp->next;
1345 }
1346 } else if (value != NULL) {
1347 ret->children = xmlNewDocText(ctxt->myDoc, value);
1348 ret->last = ret->children;
1349 if (ret->children != NULL)
1350 ret->children->parent = (xmlNodePtr) ret;
1351 }
1352 }
1353
Daniel Veillard4432df22003-09-28 18:58:27 +00001354#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001355 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1356 ctxt->myDoc && ctxt->myDoc->intSubset) {
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001357
Daniel Veillard1af9a412003-08-20 22:54:39 +00001358 /*
1359 * If we don't substitute entities, the validation should be
1360 * done on a value with replaced entities anyway.
1361 */
1362 if (!ctxt->replaceEntities) {
1363 xmlChar *val;
1364
1365 ctxt->depth++;
1366 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1367 0,0,0);
1368 ctxt->depth--;
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001369
Daniel Veillard1af9a412003-08-20 22:54:39 +00001370 if (val == NULL)
1371 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1372 ctxt->myDoc, ctxt->node, ret, value);
1373 else {
1374 xmlChar *nvalnorm;
1375
1376 /*
1377 * Do the last stage of the attribute normalization
1378 * It need to be done twice ... it's an extra burden related
1379 * to the ability to keep xmlSAX2References in attributes
1380 */
1381 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1382 ctxt->node, fullname, val);
1383 if (nvalnorm != NULL) {
1384 xmlFree(val);
1385 val = nvalnorm;
1386 }
1387
1388 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1389 ctxt->myDoc, ctxt->node, ret, val);
1390 xmlFree(val);
1391 }
1392 } else {
1393 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1394 ctxt->node, ret, value);
1395 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001396 } else
1397#endif /* LIBXML_VALID_ENABLED */
1398 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001399 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1400 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1401 /*
1402 * when validating, the ID registration is done at the attribute
1403 * validation level. Otherwise we have to do specific handling here.
1404 */
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00001405 if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001406 /*
1407 * Add the xml:id value
1408 *
1409 * Open issue: normalization of the value.
1410 */
Daniel Veillard68cb4b22004-04-18 20:55:39 +00001411 if (xmlValidateNCName(value, 1) != 0) {
1412 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1413 "xml:id : attribute value %s is not an NCName\n",
1414 (const char *) value, NULL);
1415 }
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00001416 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00001417 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1418 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1419 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1420 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001421 }
1422
1423error:
1424 if (nval != NULL)
1425 xmlFree(nval);
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001426 if (ns != NULL)
Daniel Veillard1af9a412003-08-20 22:54:39 +00001427 xmlFree(ns);
1428}
1429
Daniel Veillard1af9a412003-08-20 22:54:39 +00001430/*
1431 * xmlCheckDefaultedAttributes:
1432 *
1433 * Check defaulted attributes from the DTD
1434 */
1435static void
1436xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1437 const xmlChar *prefix, const xmlChar **atts) {
1438 xmlElementPtr elemDecl;
1439 const xmlChar *att;
1440 int internal = 1;
1441 int i;
1442
1443 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1444 if (elemDecl == NULL) {
1445 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1446 internal = 0;
1447 }
1448
1449process_external_subset:
1450
1451 if (elemDecl != NULL) {
1452 xmlAttributePtr attr = elemDecl->attributes;
1453 /*
1454 * Check against defaulted attributes from the external subset
1455 * if the document is stamped as standalone
1456 */
1457 if ((ctxt->myDoc->standalone == 1) &&
1458 (ctxt->myDoc->extSubset != NULL) &&
1459 (ctxt->validate)) {
1460 while (attr != NULL) {
1461 if ((attr->defaultValue != NULL) &&
1462 (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1463 attr->elem, attr->name,
1464 attr->prefix) == attr) &&
1465 (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1466 attr->elem, attr->name,
1467 attr->prefix) == NULL)) {
1468 xmlChar *fulln;
1469
1470 if (attr->prefix != NULL) {
1471 fulln = xmlStrdup(attr->prefix);
1472 fulln = xmlStrcat(fulln, BAD_CAST ":");
1473 fulln = xmlStrcat(fulln, attr->name);
1474 } else {
1475 fulln = xmlStrdup(attr->name);
1476 }
Jim Meyering669e88c2009-07-29 11:33:32 +02001477 if (fulln == NULL) {
1478 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1479 break;
1480 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001481
1482 /*
1483 * Check that the attribute is not declared in the
1484 * serialization
1485 */
1486 att = NULL;
1487 if (atts != NULL) {
1488 i = 0;
1489 att = atts[i];
1490 while (att != NULL) {
1491 if (xmlStrEqual(att, fulln))
1492 break;
1493 i += 2;
1494 att = atts[i];
1495 }
1496 }
1497 if (att == NULL) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001498 xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
Daniel Veillard1af9a412003-08-20 22:54:39 +00001499 "standalone: attribute %s on %s defaulted from external subset\n",
Daniel Veillard427174f2003-12-10 10:42:59 +00001500 (const char *)fulln,
1501 (const char *)attr->elem);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001502 }
Daniel Veillard023d0ba2009-07-29 11:34:50 +02001503 xmlFree(fulln);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001504 }
1505 attr = attr->nexth;
1506 }
1507 }
1508
1509 /*
1510 * Actually insert defaulted values when needed
1511 */
1512 attr = elemDecl->attributes;
1513 while (attr != NULL) {
1514 /*
1515 * Make sure that attributes redefinition occuring in the
1516 * internal subset are not overriden by definitions in the
1517 * external subset.
1518 */
1519 if (attr->defaultValue != NULL) {
1520 /*
1521 * the element should be instantiated in the tree if:
1522 * - this is a namespace prefix
1523 * - the user required for completion in the tree
1524 * like XSLT
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001525 * - there isn't already an attribute definition
Daniel Veillard1af9a412003-08-20 22:54:39 +00001526 * in the internal subset overriding it.
1527 */
1528 if (((attr->prefix != NULL) &&
1529 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1530 ((attr->prefix == NULL) &&
1531 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1532 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1533 xmlAttributePtr tst;
1534
1535 tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1536 attr->elem, attr->name,
1537 attr->prefix);
1538 if ((tst == attr) || (tst == NULL)) {
1539 xmlChar fn[50];
1540 xmlChar *fulln;
1541
1542 fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1543 if (fulln == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001544 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001545 return;
1546 }
1547
1548 /*
1549 * Check that the attribute is not declared in the
1550 * serialization
1551 */
1552 att = NULL;
1553 if (atts != NULL) {
1554 i = 0;
1555 att = atts[i];
1556 while (att != NULL) {
1557 if (xmlStrEqual(att, fulln))
1558 break;
1559 i += 2;
1560 att = atts[i];
1561 }
1562 }
1563 if (att == NULL) {
1564 xmlSAX2AttributeInternal(ctxt, fulln,
1565 attr->defaultValue, prefix);
1566 }
1567 if ((fulln != fn) && (fulln != attr->name))
1568 xmlFree(fulln);
1569 }
1570 }
1571 }
1572 attr = attr->nexth;
1573 }
1574 if (internal == 1) {
1575 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1576 name, prefix);
1577 internal = 0;
1578 goto process_external_subset;
1579 }
1580 }
1581}
1582
1583/**
1584 * xmlSAX2StartElement:
1585 * @ctx: the user data (XML parser context)
1586 * @fullname: The element name, including namespace prefix
1587 * @atts: An array of name/value attributes pairs, NULL terminated
1588 *
1589 * called when an opening tag has been processed.
1590 */
1591void
1592xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1593{
1594 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1595 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001596 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001597 xmlNsPtr ns;
1598 xmlChar *name;
1599 xmlChar *prefix;
1600 const xmlChar *att;
1601 const xmlChar *value;
1602 int i;
1603
Daniel Veillarda521d282004-11-09 14:59:59 +00001604 if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001605 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001606#ifdef DEBUG_SAX
1607 xmlGenericError(xmlGenericErrorContext,
1608 "SAX.xmlSAX2StartElement(%s)\n", fullname);
1609#endif
1610
1611 /*
1612 * First check on validity:
1613 */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001614 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001615 ((ctxt->myDoc->intSubset == NULL) ||
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001616 ((ctxt->myDoc->intSubset->notations == NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001617 (ctxt->myDoc->intSubset->elements == NULL) &&
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001618 (ctxt->myDoc->intSubset->attributes == NULL) &&
Daniel Veillard1af9a412003-08-20 22:54:39 +00001619 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00001620 xmlErrValid(ctxt, XML_ERR_NO_DTD,
1621 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001622 ctxt->validate = 0;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001623 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001624
Daniel Veillard1af9a412003-08-20 22:54:39 +00001625
1626 /*
1627 * Split the full name into a namespace prefix and the tag name
1628 */
1629 name = xmlSplitQName(ctxt, fullname, &prefix);
1630
1631
1632 /*
1633 * Note : the namespace resolution is deferred until the end of the
1634 * attributes parsing, since local namespace can be defined as
1635 * an attribute at this level.
1636 */
1637 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1638 if (ret == NULL) {
1639 if (prefix != NULL)
1640 xmlFree(prefix);
William M. Brack42331a92004-07-29 07:07:16 +00001641 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
Daniel Veillard1af9a412003-08-20 22:54:39 +00001642 return;
1643 }
1644 if (ctxt->myDoc->children == NULL) {
1645#ifdef DEBUG_SAX_TREE
1646 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1647#endif
1648 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1649 } else if (parent == NULL) {
1650 parent = ctxt->myDoc->children;
1651 }
1652 ctxt->nodemem = -1;
1653 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00001654 if (ctxt->input != NULL) {
1655 if (ctxt->input->line < 65535)
1656 ret->line = (short) ctxt->input->line;
1657 else
1658 ret->line = 65535;
1659 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001660 }
1661
1662 /*
1663 * We are parsing a new node.
1664 */
1665#ifdef DEBUG_SAX_TREE
1666 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1667#endif
1668 nodePush(ctxt, ret);
1669
1670 /*
1671 * Link the child element
1672 */
1673 if (parent != NULL) {
1674 if (parent->type == XML_ELEMENT_NODE) {
1675#ifdef DEBUG_SAX_TREE
1676 xmlGenericError(xmlGenericErrorContext,
1677 "adding child %s to %s\n", name, parent->name);
1678#endif
1679 xmlAddChild(parent, ret);
1680 } else {
1681#ifdef DEBUG_SAX_TREE
1682 xmlGenericError(xmlGenericErrorContext,
1683 "adding sibling %s to ", name);
1684 xmlDebugDumpOneNode(stderr, parent, 0);
1685#endif
1686 xmlAddSibling(parent, ret);
1687 }
1688 }
1689
1690 /*
1691 * Insert all the defaulted attributes from the DTD especially namespaces
1692 */
1693 if ((!ctxt->html) &&
1694 ((ctxt->myDoc->intSubset != NULL) ||
1695 (ctxt->myDoc->extSubset != NULL))) {
1696 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1697 }
1698
1699 /*
1700 * process all the attributes whose name start with "xmlns"
1701 */
1702 if (atts != NULL) {
1703 i = 0;
1704 att = atts[i++];
1705 value = atts[i++];
1706 if (!ctxt->html) {
1707 while ((att != NULL) && (value != NULL)) {
1708 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1709 (att[3] == 'n') && (att[4] == 's'))
1710 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1711
1712 att = atts[i++];
1713 value = atts[i++];
1714 }
1715 }
1716 }
1717
1718 /*
1719 * Search the namespace, note that since the attributes have been
1720 * processed, the local namespaces are available.
1721 */
1722 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1723 if ((ns == NULL) && (parent != NULL))
1724 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1725 if ((prefix != NULL) && (ns == NULL)) {
1726 ns = xmlNewNs(ret, NULL, prefix);
Daniel Veillard77aad342006-07-13 06:21:09 +00001727 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1728 "Namespace prefix %s is not defined\n",
1729 prefix, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001730 }
1731
1732 /*
1733 * set the namespace node, making sure that if the default namspace
1734 * is unbound on a parent we simply kee it NULL
1735 */
1736 if ((ns != NULL) && (ns->href != NULL) &&
1737 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1738 xmlSetNs(ret, ns);
1739
1740 /*
1741 * process all the other attributes
1742 */
1743 if (atts != NULL) {
1744 i = 0;
1745 att = atts[i++];
1746 value = atts[i++];
1747 if (ctxt->html) {
1748 while (att != NULL) {
1749 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1750 att = atts[i++];
1751 value = atts[i++];
1752 }
1753 } else {
1754 while ((att != NULL) && (value != NULL)) {
1755 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1756 (att[3] != 'n') || (att[4] != 's'))
1757 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1758
1759 /*
1760 * Next ones
1761 */
1762 att = atts[i++];
1763 value = atts[i++];
1764 }
1765 }
1766 }
1767
Daniel Veillard4432df22003-09-28 18:58:27 +00001768#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001769 /*
1770 * If it's the Document root, finish the DTD validation and
1771 * check the document root element for validity
1772 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00001773 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001774 int chk;
1775
1776 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1777 if (chk <= 0)
1778 ctxt->valid = 0;
1779 if (chk < 0)
1780 ctxt->wellFormed = 0;
1781 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00001782 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001783 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001784#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001785
1786 if (prefix != NULL)
1787 xmlFree(prefix);
1788
1789}
1790
1791/**
1792 * xmlSAX2EndElement:
1793 * @ctx: the user data (XML parser context)
1794 * @name: The element name
1795 *
1796 * called when the end of an element has been detected.
1797 */
1798void
1799xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1800{
1801 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001802 xmlNodePtr cur;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001803
Daniel Veillard34099b42004-11-04 17:34:35 +00001804 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001805 cur = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001806#ifdef DEBUG_SAX
1807 if (name == NULL)
1808 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1809 else
1810 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1811#endif
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001812
Daniel Veillard1af9a412003-08-20 22:54:39 +00001813 /* Capture end position and add node */
1814 if (cur != NULL && ctxt->record_info) {
Pavel Andrejs8ad4da52012-05-08 11:01:12 +08001815 ctxt->nodeInfo->end_pos = ctxt->input->cur - ctxt->input->base;
1816 ctxt->nodeInfo->end_line = ctxt->input->line;
1817 ctxt->nodeInfo->node = cur;
1818 xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001819 }
1820 ctxt->nodemem = -1;
1821
Daniel Veillard4432df22003-09-28 18:58:27 +00001822#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001823 if (ctxt->validate && ctxt->wellFormed &&
1824 ctxt->myDoc && ctxt->myDoc->intSubset)
1825 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1826 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001827#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001828
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001829
Daniel Veillard1af9a412003-08-20 22:54:39 +00001830 /*
1831 * end of parsing of this node.
1832 */
1833#ifdef DEBUG_SAX_TREE
1834 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1835#endif
1836 nodePop(ctxt);
1837}
Nicolas Le Cam77b5b462014-02-10 10:32:45 +08001838#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001839
Daniel Veillarde57ec792003-09-10 10:50:59 +00001840/*
Daniel Veillard19895052003-09-17 13:59:32 +00001841 * xmlSAX2TextNode:
1842 * @ctxt: the parser context
1843 * @str: the input string
1844 * @len: the string length
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001845 *
Daniel Veillard968a03a2012-08-13 12:41:33 +08001846 * Callback for a text node
Daniel Veillard19895052003-09-17 13:59:32 +00001847 *
1848 * Returns the newly allocated string or NULL if not needed or error
1849 */
1850static xmlNodePtr
1851xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1852 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001853 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001854
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001855 /*
1856 * Allocate
1857 */
Daniel Veillard19895052003-09-17 13:59:32 +00001858 if (ctxt->freeElems != NULL) {
1859 ret = ctxt->freeElems;
1860 ctxt->freeElems = ret->next;
1861 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001862 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001863 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001864 }
1865 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001866 xmlErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard19895052003-09-17 13:59:32 +00001867 return(NULL);
1868 }
Daniel Veillard8874b942005-08-25 13:19:21 +00001869 memset(ret, 0, sizeof(xmlNode));
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001870 /*
1871 * intern the formatting blanks found between tags, or the
1872 * very short strings
1873 */
1874 if (ctxt->dictNames) {
1875 xmlChar cur = str[len];
1876
Daniel Veillard8874b942005-08-25 13:19:21 +00001877 if ((len < (int) (2 * sizeof(void *))) &&
1878 (ctxt->options & XML_PARSE_COMPACT)) {
Daniel Veillard968a03a2012-08-13 12:41:33 +08001879 /* store the string in the node overriding properties and nsDef */
Daniel Veillard8874b942005-08-25 13:19:21 +00001880 xmlChar *tmp = (xmlChar *) &(ret->properties);
1881 memcpy(tmp, str, len);
1882 tmp[len] = 0;
1883 intern = tmp;
1884 } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001885 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001886 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001887 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001888 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001889 int i;
1890
1891 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001892 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001893 }
1894 intern = xmlDictLookup(ctxt->dict, str, len);
1895 }
1896 }
1897skip:
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001898 ret->type = XML_TEXT_NODE;
1899
1900 ret->name = xmlStringText;
William M. Brack9f797ab2004-07-28 07:40:12 +00001901 if (intern == NULL) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001902 ret->content = xmlStrndup(str, len);
William M. Brack9f797ab2004-07-28 07:40:12 +00001903 if (ret->content == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001904 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1905 xmlFree(ret);
William M. Brack9f797ab2004-07-28 07:40:12 +00001906 return(NULL);
1907 }
1908 } else
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001909 ret->content = (xmlChar *) intern;
1910
Daniel Veillard968a03a2012-08-13 12:41:33 +08001911 if (ctxt->linenumbers) {
1912 if (ctxt->input != NULL) {
1913 if (ctxt->input->line < 65535)
1914 ret->line = (short) ctxt->input->line;
1915 else {
1916 ret->line = 65535;
1917 if (ctxt->options & XML_PARSE_BIG_LINES)
akirilov4e91cfd2018-06-01 13:46:04 -07001918 ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
Daniel Veillard968a03a2012-08-13 12:41:33 +08001919 }
1920 }
1921 }
Daniel Veillard45efd082008-07-07 13:52:52 +00001922
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001923 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1924 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001925 return(ret);
1926}
1927
Daniel Veillard4432df22003-09-28 18:58:27 +00001928#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001929/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001930 * xmlSAX2DecodeAttrEntities:
1931 * @ctxt: the parser context
1932 * @str: the input string
1933 * @len: the string length
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001934 *
Daniel Veillarde57ec792003-09-10 10:50:59 +00001935 * Remove the entities from an attribute value
1936 *
1937 * Returns the newly allocated string or NULL if not needed or error
1938 */
1939static xmlChar *
1940xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1941 const xmlChar *end) {
1942 const xmlChar *in;
1943 xmlChar *ret;
1944
1945 in = str;
1946 while (in < end)
1947 if (*in++ == '&')
1948 goto decode;
1949 return(NULL);
1950decode:
1951 ctxt->depth++;
1952 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1953 XML_SUBSTITUTE_REF, 0,0,0);
1954 ctxt->depth--;
1955 return(ret);
1956}
Daniel Veillard4432df22003-09-28 18:58:27 +00001957#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001958
1959/**
1960 * xmlSAX2AttributeNs:
1961 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001962 * @localname: the local name of the attribute
1963 * @prefix: the attribute namespace prefix if available
1964 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001965 * @value: Start of the attribute value
1966 * @valueend: end of the attribute value
1967 *
1968 * Handle an attribute that has been read by the parser.
1969 * The default handling is to convert the attribute into an
1970 * DOM subtree and past it in a new xmlAttr element added to
1971 * the element.
1972 */
1973static void
1974xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1975 const xmlChar * localname,
1976 const xmlChar * prefix,
1977 const xmlChar * value,
1978 const xmlChar * valueend)
1979{
1980 xmlAttrPtr ret;
1981 xmlNsPtr namespace = NULL;
1982 xmlChar *dup = NULL;
1983
Daniel Veillarde57ec792003-09-10 10:50:59 +00001984 /*
1985 * Note: if prefix == NULL, the attribute is not in the default namespace
1986 */
1987 if (prefix != NULL)
1988 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1989
Daniel Veillard8a44e592003-09-15 14:50:06 +00001990 /*
1991 * allocate the node
1992 */
1993 if (ctxt->freeAttrs != NULL) {
1994 ret = ctxt->freeAttrs;
1995 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00001996 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00001997 memset(ret, 0, sizeof(xmlAttr));
1998 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00001999
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002000 ret->parent = ctxt->node;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002001 ret->doc = ctxt->myDoc;
2002 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002003
Daniel Veillard8a44e592003-09-15 14:50:06 +00002004 if (ctxt->dictNames)
2005 ret->name = localname;
2006 else
2007 ret->name = xmlStrdup(localname);
2008
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002009 /* link at the end to preserv order, TODO speed up with a last */
2010 if (ctxt->node->properties == NULL) {
2011 ctxt->node->properties = ret;
2012 } else {
2013 xmlAttrPtr prev = ctxt->node->properties;
2014
2015 while (prev->next != NULL) prev = prev->next;
2016 prev->next = ret;
2017 ret->prev = prev;
2018 }
2019
Daniel Veillard8a44e592003-09-15 14:50:06 +00002020 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2021 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
2022 } else {
2023 if (ctxt->dictNames)
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002024 ret = xmlNewNsPropEatName(ctxt->node, namespace,
Daniel Veillard8a44e592003-09-15 14:50:06 +00002025 (xmlChar *) localname, NULL);
2026 else
2027 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
2028 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002029 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002030 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002031 }
2032 }
2033
Daniel Veillard8a44e592003-09-15 14:50:06 +00002034 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
2035 xmlNodePtr tmp;
2036
Daniel Veillard19895052003-09-17 13:59:32 +00002037 /*
2038 * We know that if there is an entity reference, then
2039 * the string has been dup'ed and terminates with 0
2040 * otherwise with ' or "
2041 */
2042 if (*valueend != 0) {
2043 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2044 ret->children = tmp;
2045 ret->last = tmp;
2046 if (tmp != NULL) {
2047 tmp->doc = ret->doc;
2048 tmp->parent = (xmlNodePtr) ret;
2049 }
2050 } else {
2051 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
2052 valueend - value);
2053 tmp = ret->children;
2054 while (tmp != NULL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00002055 tmp->doc = ret->doc;
Daniel Veillard19895052003-09-17 13:59:32 +00002056 tmp->parent = (xmlNodePtr) ret;
2057 if (tmp->next == NULL)
2058 ret->last = tmp;
2059 tmp = tmp->next;
2060 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002061 }
2062 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002063 xmlNodePtr tmp;
2064
2065 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2066 ret->children = tmp;
2067 ret->last = tmp;
2068 if (tmp != NULL) {
2069 tmp->doc = ret->doc;
2070 tmp->parent = (xmlNodePtr) ret;
2071 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002072 }
2073
Daniel Veillard4432df22003-09-28 18:58:27 +00002074#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002075 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2076 ctxt->myDoc && ctxt->myDoc->intSubset) {
2077 /*
2078 * If we don't substitute entities, the validation should be
2079 * done on a value with replaced entities anyway.
2080 */
2081 if (!ctxt->replaceEntities) {
2082 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
2083 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00002084 if (*valueend == 0) {
2085 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2086 ctxt->myDoc, ctxt->node, ret, value);
2087 } else {
2088 /*
2089 * That should already be normalized.
2090 * cheaper to finally allocate here than duplicate
2091 * entry points in the full validation code
2092 */
2093 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002094
Daniel Veillard62998c02003-09-15 12:56:36 +00002095 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2096 ctxt->myDoc, ctxt->node, ret, dup);
2097 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002098 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00002099 /*
2100 * dup now contains a string of the flattened attribute
2101 * content with entities substitued. Check if we need to
2102 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002103 * It need to be done twice ... it's an extra burden related
2104 * to the ability to keep references in attributes
2105 */
Daniel Veillard62998c02003-09-15 12:56:36 +00002106 if (ctxt->attsSpecial != NULL) {
2107 xmlChar *nvalnorm;
2108 xmlChar fn[50];
2109 xmlChar *fullname;
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002110
Daniel Veillard62998c02003-09-15 12:56:36 +00002111 fullname = xmlBuildQName(localname, prefix, fn, 50);
2112 if (fullname != NULL) {
2113 ctxt->vctxt.valid = 1;
2114 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2115 &ctxt->vctxt, ctxt->myDoc,
2116 ctxt->node, fullname, dup);
2117 if (ctxt->vctxt.valid != 1)
2118 ctxt->valid = 0;
2119
2120 if ((fullname != fn) && (fullname != localname))
2121 xmlFree(fullname);
2122 if (nvalnorm != NULL) {
2123 xmlFree(dup);
2124 dup = nvalnorm;
2125 }
2126 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002127 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002128
2129 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2130 ctxt->myDoc, ctxt->node, ret, dup);
2131 }
2132 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00002133 /*
2134 * if entities already have been substitued, then
2135 * the attribute as passed is already normalized
2136 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002137 dup = xmlStrndup(value, valueend - value);
2138
2139 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2140 ctxt->myDoc, ctxt->node, ret, dup);
2141 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002142 } else
2143#endif /* LIBXML_VALID_ENABLED */
2144 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002145 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2146 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
2147 /*
2148 * when validating, the ID registration is done at the attribute
2149 * validation level. Otherwise we have to do specific handling here.
2150 */
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002151 if ((prefix == ctxt->str_xml) &&
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002152 (localname[0] == 'i') && (localname[1] == 'd') &&
2153 (localname[2] == 0)) {
2154 /*
2155 * Add the xml:id value
2156 *
2157 * Open issue: normalization of the value.
2158 */
2159 if (dup == NULL)
2160 dup = xmlStrndup(value, valueend - value);
Nicolas Le Cam52010c62013-06-16 08:55:08 +02002161#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
William M. Brack5ef2f812004-05-23 23:56:47 +00002162#ifdef LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00002163 if (xmlValidateNCName(dup, 1) != 0) {
2164 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2165 "xml:id : attribute value %s is not an NCName\n",
2166 (const char *) dup, NULL);
2167 }
William M. Brack3f147372004-05-22 01:09:26 +00002168#endif
Nicolas Le Cam52010c62013-06-16 08:55:08 +02002169#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002170 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002171 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2172 /* might be worth duplicate entry points and not copy */
2173 if (dup == NULL)
2174 dup = xmlStrndup(value, valueend - value);
2175 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2176 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2177 if (dup == NULL)
2178 dup = xmlStrndup(value, valueend - value);
2179 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002180 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002181 }
2182 if (dup != NULL)
2183 xmlFree(dup);
2184}
2185
2186/**
2187 * xmlSAX2StartElementNs:
2188 * @ctx: the user data (XML parser context)
2189 * @localname: the local name of the element
2190 * @prefix: the element namespace prefix if available
2191 * @URI: the element namespace name if available
2192 * @nb_namespaces: number of namespace definitions on that node
2193 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2194 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002195 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002196 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2197 * attribute values.
2198 *
2199 * SAX2 callback when an element start has been detected by the parser.
2200 * It provides the namespace informations for the element, as well as
2201 * the new namespace declarations on the element.
2202 */
2203void
2204xmlSAX2StartElementNs(void *ctx,
2205 const xmlChar *localname,
2206 const xmlChar *prefix,
2207 const xmlChar *URI,
2208 int nb_namespaces,
2209 const xmlChar **namespaces,
2210 int nb_attributes,
2211 int nb_defaulted,
2212 const xmlChar **attributes)
2213{
2214 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2215 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002216 xmlNodePtr parent;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002217 xmlNsPtr last = NULL, ns;
2218 const xmlChar *uri, *pref;
Daniel Veillard77b77b12012-01-26 19:11:02 +08002219 xmlChar *lname = NULL;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002220 int i, j;
2221
Daniel Veillard34099b42004-11-04 17:34:35 +00002222 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002223 parent = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002224 /*
2225 * First check on validity:
2226 */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002227 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002228 ((ctxt->myDoc->intSubset == NULL) ||
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002229 ((ctxt->myDoc->intSubset->notations == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002230 (ctxt->myDoc->intSubset->elements == NULL) &&
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002231 (ctxt->myDoc->intSubset->attributes == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002232 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillard6c91aa32012-10-25 15:33:59 +08002233 xmlErrValid(ctxt, XML_DTD_NO_DTD,
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002234 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002235 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002236 }
2237
Daniel Veillard8a44e592003-09-15 14:50:06 +00002238 /*
Daniel Veillard77b77b12012-01-26 19:11:02 +08002239 * Take care of the rare case of an undefined namespace prefix
2240 */
2241 if ((prefix != NULL) && (URI == NULL)) {
2242 if (ctxt->dictNames) {
2243 const xmlChar *fullname;
2244
2245 fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
2246 if (fullname != NULL)
2247 localname = fullname;
2248 } else {
2249 lname = xmlBuildQName(localname, prefix, NULL, 0);
2250 }
2251 }
2252 /*
Daniel Veillard8a44e592003-09-15 14:50:06 +00002253 * allocate the node
2254 */
2255 if (ctxt->freeElems != NULL) {
2256 ret = ctxt->freeElems;
2257 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002258 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002259 memset(ret, 0, sizeof(xmlNode));
2260 ret->type = XML_ELEMENT_NODE;
2261
2262 if (ctxt->dictNames)
2263 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002264 else {
Daniel Veillard77b77b12012-01-26 19:11:02 +08002265 if (lname == NULL)
2266 ret->name = xmlStrdup(localname);
2267 else
2268 ret->name = lname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002269 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002270 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002271 return;
2272 }
2273 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002274 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2275 xmlRegisterNodeDefaultValue(ret);
2276 } else {
2277 if (ctxt->dictNames)
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002278 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
Daniel Veillard8a44e592003-09-15 14:50:06 +00002279 (xmlChar *) localname, NULL);
Daniel Veillard77b77b12012-01-26 19:11:02 +08002280 else if (lname == NULL)
Daniel Veillard8a44e592003-09-15 14:50:06 +00002281 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
Daniel Veillard77b77b12012-01-26 19:11:02 +08002282 else
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002283 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
Daniel Veillard77b77b12012-01-26 19:11:02 +08002284 (xmlChar *) lname, NULL);
Daniel Veillard8a44e592003-09-15 14:50:06 +00002285 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002286 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002287 return;
2288 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002289 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002290 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002291 if (ctxt->input != NULL) {
2292 if (ctxt->input->line < 65535)
2293 ret->line = (short) ctxt->input->line;
2294 else
2295 ret->line = 65535;
2296 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002297 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002298
Tim Elliott71a243d2012-01-17 19:25:08 -08002299 if (parent == NULL) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002300 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002301 }
2302 /*
2303 * Build the namespace list
2304 */
2305 for (i = 0,j = 0;j < nb_namespaces;j++) {
2306 pref = namespaces[i++];
2307 uri = namespaces[i++];
2308 ns = xmlNewNs(NULL, uri, pref);
2309 if (ns != NULL) {
2310 if (last == NULL) {
2311 ret->nsDef = last = ns;
2312 } else {
2313 last->next = ns;
2314 last = ns;
2315 }
2316 if ((URI != NULL) && (prefix == pref))
2317 ret->ns = ns;
2318 } else {
Daniel Veillardaa54d372010-09-09 18:17:47 +02002319 /*
2320 * any out of memory error would already have been raised
akirilov4e91cfd2018-06-01 13:46:04 -07002321 * but we can't be guaranteed it's the actual error due to the
Daniel Veillardaa54d372010-09-09 18:17:47 +02002322 * API, best is to skip in this case
2323 */
2324 continue;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002325 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002326#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002327 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2328 ctxt->myDoc && ctxt->myDoc->intSubset) {
2329 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2330 ret, prefix, ns, uri);
2331 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002332#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002333 }
2334 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002335
2336 /*
2337 * We are parsing a new node.
2338 */
2339 nodePush(ctxt, ret);
2340
2341 /*
2342 * Link the child element
2343 */
2344 if (parent != NULL) {
2345 if (parent->type == XML_ELEMENT_NODE) {
2346 xmlAddChild(parent, ret);
2347 } else {
2348 xmlAddSibling(parent, ret);
2349 }
2350 }
2351
2352 /*
2353 * Insert the defaulted attributes from the DTD only if requested:
2354 */
2355 if ((nb_defaulted != 0) &&
2356 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2357 nb_attributes -= nb_defaulted;
2358
2359 /*
2360 * Search the namespace if it wasn't already found
William M. Brackbf5cf212004-08-31 06:47:17 +00002361 * Note that, if prefix is NULL, this searches for the default Ns
Daniel Veillarde57ec792003-09-10 10:50:59 +00002362 */
2363 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brackbf5cf212004-08-31 06:47:17 +00002364 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillard6977c6c2006-01-04 14:03:10 +00002365 if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2366 ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2367 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002368 if (ret->ns == NULL) {
2369 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002370 if (ns == NULL) {
Daniel Veillard6977c6c2006-01-04 14:03:10 +00002371
William M. Brack42331a92004-07-29 07:07:16 +00002372 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002373 return;
2374 }
Daniel Veillard74eaec12009-08-26 15:57:20 +02002375 if (prefix != NULL)
2376 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2377 "Namespace prefix %s was not found\n",
2378 prefix, NULL);
2379 else
2380 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2381 "Namespace default prefix was not found\n",
2382 NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002383 }
2384 }
2385
2386 /*
2387 * process all the other attributes
2388 */
2389 if (nb_attributes > 0) {
2390 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
Daniel Veillard1c989272012-01-26 19:43:06 +08002391 /*
2392 * Handle the rare case of an undefined atribute prefix
2393 */
2394 if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
2395 if (ctxt->dictNames) {
2396 const xmlChar *fullname;
2397
2398 fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
2399 attributes[j]);
2400 if (fullname != NULL) {
2401 xmlSAX2AttributeNs(ctxt, fullname, NULL,
2402 attributes[j+3], attributes[j+4]);
2403 continue;
2404 }
2405 } else {
2406 lname = xmlBuildQName(attributes[j], attributes[j+1],
2407 NULL, 0);
2408 if (lname != NULL) {
2409 xmlSAX2AttributeNs(ctxt, lname, NULL,
2410 attributes[j+3], attributes[j+4]);
2411 xmlFree(lname);
2412 continue;
2413 }
2414 }
2415 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002416 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
Daniel Veillard1c989272012-01-26 19:43:06 +08002417 attributes[j+3], attributes[j+4]);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002418 }
2419 }
2420
Daniel Veillard4432df22003-09-28 18:58:27 +00002421#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002422 /*
2423 * If it's the Document root, finish the DTD validation and
2424 * check the document root element for validity
2425 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00002426 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002427 int chk;
2428
2429 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2430 if (chk <= 0)
2431 ctxt->valid = 0;
2432 if (chk < 0)
2433 ctxt->wellFormed = 0;
2434 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00002435 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002436 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002437#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002438}
2439
2440/**
2441 * xmlSAX2EndElementNs:
2442 * @ctx: the user data (XML parser context)
2443 * @localname: the local name of the element
2444 * @prefix: the element namespace prefix if available
2445 * @URI: the element namespace name if available
2446 *
2447 * SAX2 callback when an element end has been detected by the parser.
2448 * It provides the namespace informations for the element.
2449 */
2450void
2451xmlSAX2EndElementNs(void *ctx,
2452 const xmlChar * localname ATTRIBUTE_UNUSED,
2453 const xmlChar * prefix ATTRIBUTE_UNUSED,
2454 const xmlChar * URI ATTRIBUTE_UNUSED)
2455{
2456 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2457 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002458 xmlNodePtr cur;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002459
Daniel Veillard34099b42004-11-04 17:34:35 +00002460 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002461 cur = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002462 /* Capture end position and add node */
2463 if ((ctxt->record_info) && (cur != NULL)) {
2464 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2465 node_info.end_line = ctxt->input->line;
2466 node_info.node = cur;
2467 xmlParserAddNodeInfo(ctxt, &node_info);
2468 }
2469 ctxt->nodemem = -1;
2470
Daniel Veillard4432df22003-09-28 18:58:27 +00002471#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002472 if (ctxt->validate && ctxt->wellFormed &&
2473 ctxt->myDoc && ctxt->myDoc->intSubset)
2474 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002475#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002476
2477 /*
2478 * end of parsing of this node.
2479 */
2480 nodePop(ctxt);
2481}
2482
Daniel Veillard1af9a412003-08-20 22:54:39 +00002483/**
2484 * xmlSAX2Reference:
2485 * @ctx: the user data (XML parser context)
2486 * @name: The entity name
2487 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002488 * called when an entity xmlSAX2Reference is detected.
Daniel Veillard1af9a412003-08-20 22:54:39 +00002489 */
2490void
2491xmlSAX2Reference(void *ctx, const xmlChar *name)
2492{
2493 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2494 xmlNodePtr ret;
2495
Daniel Veillard34099b42004-11-04 17:34:35 +00002496 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002497#ifdef DEBUG_SAX
2498 xmlGenericError(xmlGenericErrorContext,
2499 "SAX.xmlSAX2Reference(%s)\n", name);
2500#endif
2501 if (name[0] == '#')
2502 ret = xmlNewCharRef(ctxt->myDoc, name);
2503 else
2504 ret = xmlNewReference(ctxt->myDoc, name);
2505#ifdef DEBUG_SAX_TREE
2506 xmlGenericError(xmlGenericErrorContext,
2507 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2508#endif
Daniel Veillardb242b082008-02-08 09:56:31 +00002509 if (xmlAddChild(ctxt->node, ret) == NULL) {
2510 xmlFreeNode(ret);
2511 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002512}
2513
2514/**
2515 * xmlSAX2Characters:
2516 * @ctx: the user data (XML parser context)
2517 * @ch: a xmlChar string
2518 * @len: the number of xmlChar
2519 *
2520 * receiving some chars from the parser.
2521 */
2522void
2523xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2524{
2525 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2526 xmlNodePtr lastChild;
2527
Daniel Veillard34099b42004-11-04 17:34:35 +00002528 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002529#ifdef DEBUG_SAX
2530 xmlGenericError(xmlGenericErrorContext,
2531 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2532#endif
2533 /*
2534 * Handle the data if any. If there is no child
2535 * add it as content, otherwise if the last child is text,
2536 * concatenate it, else create a new node of type text.
2537 */
2538
2539 if (ctxt->node == NULL) {
2540#ifdef DEBUG_SAX_TREE
2541 xmlGenericError(xmlGenericErrorContext,
2542 "add chars: ctxt->node == NULL !\n");
2543#endif
2544 return;
2545 }
Daniel Veillard19895052003-09-17 13:59:32 +00002546 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002547#ifdef DEBUG_SAX_TREE
2548 xmlGenericError(xmlGenericErrorContext,
2549 "add chars to %s \n", ctxt->node->name);
2550#endif
2551
2552 /*
2553 * Here we needed an accelerator mechanism in case of very large
2554 * elements. Use an attribute in the structure !!!
2555 */
2556 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002557 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2558 if (lastChild != NULL) {
2559 ctxt->node->children = lastChild;
2560 ctxt->node->last = lastChild;
2561 lastChild->parent = ctxt->node;
2562 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002563 ctxt->nodelen = len;
2564 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002565 } else {
2566 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2567 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002568 }
2569 } else {
2570 int coalesceText = (lastChild != NULL) &&
2571 (lastChild->type == XML_TEXT_NODE) &&
2572 (lastChild->name == xmlStringText);
2573 if ((coalesceText) && (ctxt->nodemem != 0)) {
2574 /*
2575 * The whole point of maintaining nodelen and nodemem,
2576 * xmlTextConcat is too costly, i.e. compute length,
2577 * reallocate a new buffer, move data, append ch. Here
2578 * We try to minimaze realloc() uses and avoid copying
2579 * and recomputing length over and over.
2580 */
Daniel Veillard8874b942005-08-25 13:19:21 +00002581 if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2582 lastChild->content = xmlStrdup(lastChild->content);
2583 lastChild->properties = NULL;
2584 } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2585 (xmlDictOwns(ctxt->dict, lastChild->content))) {
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002586 lastChild->content = xmlStrdup(lastChild->content);
2587 }
Gaurav3e0eec42014-06-13 14:45:20 +08002588 if (lastChild->content == NULL) {
2589 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL");
Daniel Veillarda6ea72a2014-07-14 20:29:34 +08002590 return;
Gaurav3e0eec42014-06-13 14:45:20 +08002591 }
Daniel Veillard97ff9b32009-01-18 21:43:30 +00002592 if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
Daniel Veillard1fb2e0d2009-01-18 14:08:36 +00002593 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2594 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2595 return;
2596 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002597 if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002598 (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
Daniel Veillard1fb2e0d2009-01-18 14:08:36 +00002599 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2600 return;
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002601 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002602 if (ctxt->nodelen + len >= ctxt->nodemem) {
2603 xmlChar *newbuf;
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002604 size_t size;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002605
2606 size = ctxt->nodemem + len;
2607 size *= 2;
2608 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2609 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002610 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002611 return;
2612 }
2613 ctxt->nodemem = size;
2614 lastChild->content = newbuf;
2615 }
2616 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2617 ctxt->nodelen += len;
2618 lastChild->content[ctxt->nodelen] = 0;
2619 } else if (coalesceText) {
2620 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002621 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002622 }
2623 if (ctxt->node->children != NULL) {
2624 ctxt->nodelen = xmlStrlen(lastChild->content);
2625 ctxt->nodemem = ctxt->nodelen + 1;
2626 }
2627 } else {
2628 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002629 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2630 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002631 xmlAddChild(ctxt->node, lastChild);
2632 if (ctxt->node->children != NULL) {
2633 ctxt->nodelen = len;
2634 ctxt->nodemem = len + 1;
2635 }
2636 }
2637 }
2638 }
2639}
2640
2641/**
2642 * xmlSAX2IgnorableWhitespace:
2643 * @ctx: the user data (XML parser context)
2644 * @ch: a xmlChar string
2645 * @len: the number of xmlChar
2646 *
2647 * receiving some ignorable whitespaces from the parser.
2648 * UNUSED: by default the DOM building will use xmlSAX2Characters
2649 */
2650void
2651xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2652{
2653 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2654#ifdef DEBUG_SAX
2655 xmlGenericError(xmlGenericErrorContext,
2656 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2657#endif
2658}
2659
2660/**
2661 * xmlSAX2ProcessingInstruction:
2662 * @ctx: the user data (XML parser context)
2663 * @target: the target name
2664 * @data: the PI data's
2665 *
2666 * A processing instruction has been parsed.
2667 */
2668void
2669xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2670 const xmlChar *data)
2671{
2672 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2673 xmlNodePtr ret;
Daniel Veillard6128c012004-11-08 17:16:15 +00002674 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002675
Daniel Veillard34099b42004-11-04 17:34:35 +00002676 if (ctx == NULL) return;
Daniel Veillard6128c012004-11-08 17:16:15 +00002677 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002678#ifdef DEBUG_SAX
2679 xmlGenericError(xmlGenericErrorContext,
2680 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2681#endif
2682
Daniel Veillard03a53c32004-10-26 16:06:51 +00002683 ret = xmlNewDocPI(ctxt->myDoc, target, data);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002684 if (ret == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002685
Daniel Veillard73da77e2005-08-24 14:05:37 +00002686 if (ctxt->linenumbers) {
2687 if (ctxt->input != NULL) {
2688 if (ctxt->input->line < 65535)
2689 ret->line = (short) ctxt->input->line;
2690 else
2691 ret->line = 65535;
2692 }
2693 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002694 if (ctxt->inSubset == 1) {
2695 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2696 return;
2697 } else if (ctxt->inSubset == 2) {
2698 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2699 return;
2700 }
Tim Elliott71a243d2012-01-17 19:25:08 -08002701 if (parent == NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002702#ifdef DEBUG_SAX_TREE
2703 xmlGenericError(xmlGenericErrorContext,
2704 "Setting PI %s as root\n", target);
2705#endif
2706 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2707 return;
2708 }
2709 if (parent->type == XML_ELEMENT_NODE) {
2710#ifdef DEBUG_SAX_TREE
2711 xmlGenericError(xmlGenericErrorContext,
2712 "adding PI %s child to %s\n", target, parent->name);
2713#endif
2714 xmlAddChild(parent, ret);
2715 } else {
2716#ifdef DEBUG_SAX_TREE
2717 xmlGenericError(xmlGenericErrorContext,
2718 "adding PI %s sibling to ", target);
2719 xmlDebugDumpOneNode(stderr, parent, 0);
2720#endif
2721 xmlAddSibling(parent, ret);
2722 }
2723}
2724
2725/**
2726 * xmlSAX2Comment:
2727 * @ctx: the user data (XML parser context)
2728 * @value: the xmlSAX2Comment content
2729 *
2730 * A xmlSAX2Comment has been parsed.
2731 */
2732void
2733xmlSAX2Comment(void *ctx, const xmlChar *value)
2734{
2735 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2736 xmlNodePtr ret;
Daniel Veillard34099b42004-11-04 17:34:35 +00002737 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002738
Daniel Veillard34099b42004-11-04 17:34:35 +00002739 if (ctx == NULL) return;
2740 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002741#ifdef DEBUG_SAX
2742 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2743#endif
2744 ret = xmlNewDocComment(ctxt->myDoc, value);
2745 if (ret == NULL) return;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002746 if (ctxt->linenumbers) {
2747 if (ctxt->input != NULL) {
2748 if (ctxt->input->line < 65535)
2749 ret->line = (short) ctxt->input->line;
2750 else
2751 ret->line = 65535;
2752 }
2753 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002754
2755 if (ctxt->inSubset == 1) {
2756 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2757 return;
2758 } else if (ctxt->inSubset == 2) {
2759 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2760 return;
2761 }
Tim Elliott71a243d2012-01-17 19:25:08 -08002762 if (parent == NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002763#ifdef DEBUG_SAX_TREE
2764 xmlGenericError(xmlGenericErrorContext,
2765 "Setting xmlSAX2Comment as root\n");
2766#endif
2767 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2768 return;
2769 }
2770 if (parent->type == XML_ELEMENT_NODE) {
2771#ifdef DEBUG_SAX_TREE
2772 xmlGenericError(xmlGenericErrorContext,
2773 "adding xmlSAX2Comment child to %s\n", parent->name);
2774#endif
2775 xmlAddChild(parent, ret);
2776 } else {
2777#ifdef DEBUG_SAX_TREE
2778 xmlGenericError(xmlGenericErrorContext,
2779 "adding xmlSAX2Comment sibling to ");
2780 xmlDebugDumpOneNode(stderr, parent, 0);
2781#endif
2782 xmlAddSibling(parent, ret);
2783 }
2784}
2785
2786/**
2787 * xmlSAX2CDataBlock:
2788 * @ctx: the user data (XML parser context)
2789 * @value: The pcdata content
2790 * @len: the block length
2791 *
2792 * called when a pcdata block has been parsed
2793 */
2794void
2795xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2796{
2797 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2798 xmlNodePtr ret, lastChild;
2799
Daniel Veillard34099b42004-11-04 17:34:35 +00002800 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002801#ifdef DEBUG_SAX
2802 xmlGenericError(xmlGenericErrorContext,
2803 "SAX.pcdata(%.10s, %d)\n", value, len);
2804#endif
2805 lastChild = xmlGetLastChild(ctxt->node);
2806#ifdef DEBUG_SAX_TREE
2807 xmlGenericError(xmlGenericErrorContext,
2808 "add chars to %s \n", ctxt->node->name);
2809#endif
2810 if ((lastChild != NULL) &&
2811 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2812 xmlTextConcat(lastChild, value, len);
2813 } else {
2814 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
akirilov4e91cfd2018-06-01 13:46:04 -07002815 if (xmlAddChild(ctxt->node, ret) == NULL)
2816 xmlFreeNode(ret);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002817 }
2818}
2819
Daniel Veillard62998c02003-09-15 12:56:36 +00002820static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002821
Daniel Veillard81273902003-09-30 00:43:48 +00002822#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002823/**
2824 * xmlSAXDefaultVersion:
2825 * @version: the version, 1 or 2
2826 *
2827 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002828 * By default, during initialization the default is set to 2.
2829 * Note that it is generally a better coding style to use
2830 * xmlSAXVersion() to set up the version explicitly for a given
2831 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002832 *
2833 * Returns the previous value in case of success and -1 in case of error.
2834 */
2835int
2836xmlSAXDefaultVersion(int version)
2837{
2838 int ret = xmlSAX2DefaultVersionValue;
2839
2840 if ((version != 1) && (version != 2))
2841 return(-1);
2842 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002843 return(ret);
2844}
Daniel Veillard81273902003-09-30 00:43:48 +00002845#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002846
2847/**
2848 * xmlSAXVersion:
2849 * @hdlr: the SAX handler
2850 * @version: the version, 1 or 2
2851 *
2852 * Initialize the default XML SAX handler according to the version
2853 *
2854 * Returns 0 in case of success and -1 in case of error.
2855 */
2856int
2857xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2858{
2859 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002860 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002861 hdlr->startElement = NULL;
2862 hdlr->endElement = NULL;
2863 hdlr->startElementNs = xmlSAX2StartElementNs;
2864 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002865 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002866 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002867#ifdef LIBXML_SAX1_ENABLED
2868 } else if (version == 1) {
2869 hdlr->startElement = xmlSAX2StartElement;
2870 hdlr->endElement = xmlSAX2EndElement;
2871 hdlr->initialized = 1;
2872#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002873 } else
2874 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002875 hdlr->internalSubset = xmlSAX2InternalSubset;
2876 hdlr->externalSubset = xmlSAX2ExternalSubset;
2877 hdlr->isStandalone = xmlSAX2IsStandalone;
2878 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2879 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2880 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2881 hdlr->getEntity = xmlSAX2GetEntity;
2882 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2883 hdlr->entityDecl = xmlSAX2EntityDecl;
2884 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2885 hdlr->elementDecl = xmlSAX2ElementDecl;
2886 hdlr->notationDecl = xmlSAX2NotationDecl;
2887 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2888 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2889 hdlr->startDocument = xmlSAX2StartDocument;
2890 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002891 hdlr->reference = xmlSAX2Reference;
2892 hdlr->characters = xmlSAX2Characters;
2893 hdlr->cdataBlock = xmlSAX2CDataBlock;
2894 hdlr->ignorableWhitespace = xmlSAX2Characters;
2895 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2896 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002897 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002898 hdlr->error = xmlParserError;
2899 hdlr->fatalError = xmlParserError;
2900
Daniel Veillarde57ec792003-09-10 10:50:59 +00002901 return(0);
2902}
2903
2904/**
2905 * xmlSAX2InitDefaultSAXHandler:
2906 * @hdlr: the SAX handler
2907 * @warning: flag if non-zero sets the handler warning procedure
2908 *
2909 * Initialize the default XML SAX2 handler
2910 */
2911void
2912xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2913{
2914 if ((hdlr == NULL) || (hdlr->initialized != 0))
2915 return;
2916
2917 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2918 if (warning == 0)
2919 hdlr->warning = NULL;
2920 else
2921 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002922}
2923
2924/**
2925 * xmlDefaultSAXHandlerInit:
2926 *
2927 * Initialize the default SAX2 handler
2928 */
2929void
2930xmlDefaultSAXHandlerInit(void)
2931{
Daniel Veillard81273902003-09-30 00:43:48 +00002932#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002933 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002934#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002935}
2936
2937#ifdef LIBXML_HTML_ENABLED
2938
2939/**
2940 * xmlSAX2InitHtmlDefaultSAXHandler:
2941 * @hdlr: the SAX handler
2942 *
2943 * Initialize the default HTML SAX2 handler
2944 */
2945void
2946xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2947{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002948 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002949 return;
2950
2951 hdlr->internalSubset = xmlSAX2InternalSubset;
2952 hdlr->externalSubset = NULL;
2953 hdlr->isStandalone = NULL;
2954 hdlr->hasInternalSubset = NULL;
2955 hdlr->hasExternalSubset = NULL;
2956 hdlr->resolveEntity = NULL;
2957 hdlr->getEntity = xmlSAX2GetEntity;
2958 hdlr->getParameterEntity = NULL;
2959 hdlr->entityDecl = NULL;
2960 hdlr->attributeDecl = NULL;
2961 hdlr->elementDecl = NULL;
2962 hdlr->notationDecl = NULL;
2963 hdlr->unparsedEntityDecl = NULL;
2964 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2965 hdlr->startDocument = xmlSAX2StartDocument;
2966 hdlr->endDocument = xmlSAX2EndDocument;
2967 hdlr->startElement = xmlSAX2StartElement;
2968 hdlr->endElement = xmlSAX2EndElement;
2969 hdlr->reference = NULL;
2970 hdlr->characters = xmlSAX2Characters;
2971 hdlr->cdataBlock = xmlSAX2CDataBlock;
2972 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
Daniel Veillardfc484dd2004-10-22 14:34:23 +00002973 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002974 hdlr->comment = xmlSAX2Comment;
2975 hdlr->warning = xmlParserWarning;
2976 hdlr->error = xmlParserError;
2977 hdlr->fatalError = xmlParserError;
2978
Daniel Veillard092643b2003-09-25 14:29:29 +00002979 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002980}
2981
2982/**
2983 * htmlDefaultSAXHandlerInit:
2984 *
2985 * Initialize the default SAX handler
2986 */
2987void
2988htmlDefaultSAXHandlerInit(void)
2989{
Daniel Veillard092643b2003-09-25 14:29:29 +00002990 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002991}
2992
2993#endif /* LIBXML_HTML_ENABLED */
2994
2995#ifdef LIBXML_DOCB_ENABLED
2996
2997/**
2998 * xmlSAX2InitDocbDefaultSAXHandler:
2999 * @hdlr: the SAX handler
3000 *
3001 * Initialize the default DocBook SAX2 handler
3002 */
3003void
3004xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
3005{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00003006 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00003007 return;
3008
3009 hdlr->internalSubset = xmlSAX2InternalSubset;
3010 hdlr->externalSubset = NULL;
3011 hdlr->isStandalone = xmlSAX2IsStandalone;
3012 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
3013 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
3014 hdlr->resolveEntity = xmlSAX2ResolveEntity;
3015 hdlr->getEntity = xmlSAX2GetEntity;
3016 hdlr->getParameterEntity = NULL;
3017 hdlr->entityDecl = xmlSAX2EntityDecl;
3018 hdlr->attributeDecl = NULL;
3019 hdlr->elementDecl = NULL;
3020 hdlr->notationDecl = NULL;
3021 hdlr->unparsedEntityDecl = NULL;
3022 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
3023 hdlr->startDocument = xmlSAX2StartDocument;
3024 hdlr->endDocument = xmlSAX2EndDocument;
3025 hdlr->startElement = xmlSAX2StartElement;
3026 hdlr->endElement = xmlSAX2EndElement;
3027 hdlr->reference = xmlSAX2Reference;
3028 hdlr->characters = xmlSAX2Characters;
3029 hdlr->cdataBlock = NULL;
3030 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
3031 hdlr->processingInstruction = NULL;
3032 hdlr->comment = xmlSAX2Comment;
3033 hdlr->warning = xmlParserWarning;
3034 hdlr->error = xmlParserError;
3035 hdlr->fatalError = xmlParserError;
3036
Daniel Veillardffbbed42003-10-10 14:46:54 +00003037 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00003038}
3039
3040/**
3041 * docbDefaultSAXHandlerInit:
3042 *
3043 * Initialize the default SAX handler
3044 */
3045void
3046docbDefaultSAXHandlerInit(void)
3047{
Daniel Veillard092643b2003-09-25 14:29:29 +00003048 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00003049}
3050
3051#endif /* LIBXML_DOCB_ENABLED */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00003052#define bottom_SAX2
3053#include "elfgcchack.h"