blob: 7642501a18653e6d13c00fca93a049200208d2ab [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>
Nick Wellnhoferd422b952017-10-09 13:37:42 +020015#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);
Nick Wellnhofer83fb4112017-09-05 23:45:04 +02001185 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);
Nick Wellnhofer83fb4112017-09-05 23:45:04 +02001248 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;
Nick Wellnhofer83fb4112017-09-05 23:45:04 +02001319 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
Elliott Hughes7fbecab2019-01-10 16:42:03 -08001668 if (nodePush(ctxt, ret) < 0) {
1669 xmlUnlinkNode(ret);
1670 xmlFreeNode(ret);
1671 return;
1672 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00001673
1674 /*
1675 * Link the child element
1676 */
1677 if (parent != NULL) {
1678 if (parent->type == XML_ELEMENT_NODE) {
1679#ifdef DEBUG_SAX_TREE
1680 xmlGenericError(xmlGenericErrorContext,
1681 "adding child %s to %s\n", name, parent->name);
1682#endif
1683 xmlAddChild(parent, ret);
1684 } else {
1685#ifdef DEBUG_SAX_TREE
1686 xmlGenericError(xmlGenericErrorContext,
1687 "adding sibling %s to ", name);
1688 xmlDebugDumpOneNode(stderr, parent, 0);
1689#endif
1690 xmlAddSibling(parent, ret);
1691 }
1692 }
1693
1694 /*
1695 * Insert all the defaulted attributes from the DTD especially namespaces
1696 */
1697 if ((!ctxt->html) &&
1698 ((ctxt->myDoc->intSubset != NULL) ||
1699 (ctxt->myDoc->extSubset != NULL))) {
1700 xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1701 }
1702
1703 /*
1704 * process all the attributes whose name start with "xmlns"
1705 */
1706 if (atts != NULL) {
1707 i = 0;
1708 att = atts[i++];
1709 value = atts[i++];
1710 if (!ctxt->html) {
1711 while ((att != NULL) && (value != NULL)) {
1712 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1713 (att[3] == 'n') && (att[4] == 's'))
1714 xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1715
1716 att = atts[i++];
1717 value = atts[i++];
1718 }
1719 }
1720 }
1721
1722 /*
1723 * Search the namespace, note that since the attributes have been
1724 * processed, the local namespaces are available.
1725 */
1726 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1727 if ((ns == NULL) && (parent != NULL))
1728 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1729 if ((prefix != NULL) && (ns == NULL)) {
1730 ns = xmlNewNs(ret, NULL, prefix);
Daniel Veillard77aad342006-07-13 06:21:09 +00001731 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1732 "Namespace prefix %s is not defined\n",
1733 prefix, NULL);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001734 }
1735
1736 /*
1737 * set the namespace node, making sure that if the default namspace
1738 * is unbound on a parent we simply kee it NULL
1739 */
1740 if ((ns != NULL) && (ns->href != NULL) &&
1741 ((ns->href[0] != 0) || (ns->prefix != NULL)))
1742 xmlSetNs(ret, ns);
1743
1744 /*
1745 * process all the other attributes
1746 */
1747 if (atts != NULL) {
1748 i = 0;
1749 att = atts[i++];
1750 value = atts[i++];
1751 if (ctxt->html) {
1752 while (att != NULL) {
1753 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1754 att = atts[i++];
1755 value = atts[i++];
1756 }
1757 } else {
1758 while ((att != NULL) && (value != NULL)) {
1759 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1760 (att[3] != 'n') || (att[4] != 's'))
1761 xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1762
1763 /*
1764 * Next ones
1765 */
1766 att = atts[i++];
1767 value = atts[i++];
1768 }
1769 }
1770 }
1771
Daniel Veillard4432df22003-09-28 18:58:27 +00001772#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001773 /*
1774 * If it's the Document root, finish the DTD validation and
1775 * check the document root element for validity
1776 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00001777 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00001778 int chk;
1779
1780 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1781 if (chk <= 0)
1782 ctxt->valid = 0;
1783 if (chk < 0)
1784 ctxt->wellFormed = 0;
1785 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00001786 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001787 }
Daniel Veillard4432df22003-09-28 18:58:27 +00001788#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001789
1790 if (prefix != NULL)
1791 xmlFree(prefix);
1792
1793}
1794
1795/**
1796 * xmlSAX2EndElement:
1797 * @ctx: the user data (XML parser context)
1798 * @name: The element name
1799 *
1800 * called when the end of an element has been detected.
1801 */
1802void
1803xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1804{
1805 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001806 xmlNodePtr cur;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001807
Daniel Veillard34099b42004-11-04 17:34:35 +00001808 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00001809 cur = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00001810#ifdef DEBUG_SAX
1811 if (name == NULL)
1812 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1813 else
1814 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1815#endif
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001816
Daniel Veillard1af9a412003-08-20 22:54:39 +00001817 /* Capture end position and add node */
1818 if (cur != NULL && ctxt->record_info) {
Pavel Andrejs8ad4da52012-05-08 11:01:12 +08001819 ctxt->nodeInfo->end_pos = ctxt->input->cur - ctxt->input->base;
1820 ctxt->nodeInfo->end_line = ctxt->input->line;
1821 ctxt->nodeInfo->node = cur;
1822 xmlParserAddNodeInfo(ctxt, ctxt->nodeInfo);
Daniel Veillard1af9a412003-08-20 22:54:39 +00001823 }
1824 ctxt->nodemem = -1;
1825
Daniel Veillard4432df22003-09-28 18:58:27 +00001826#ifdef LIBXML_VALID_ENABLED
Daniel Veillard1af9a412003-08-20 22:54:39 +00001827 if (ctxt->validate && ctxt->wellFormed &&
1828 ctxt->myDoc && ctxt->myDoc->intSubset)
1829 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1830 cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00001831#endif /* LIBXML_VALID_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001832
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001833
Daniel Veillard1af9a412003-08-20 22:54:39 +00001834 /*
1835 * end of parsing of this node.
1836 */
1837#ifdef DEBUG_SAX_TREE
1838 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1839#endif
1840 nodePop(ctxt);
1841}
Nicolas Le Cam77b5b462014-02-10 10:32:45 +08001842#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00001843
Daniel Veillarde57ec792003-09-10 10:50:59 +00001844/*
Daniel Veillard19895052003-09-17 13:59:32 +00001845 * xmlSAX2TextNode:
1846 * @ctxt: the parser context
1847 * @str: the input string
1848 * @len: the string length
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001849 *
Daniel Veillard968a03a2012-08-13 12:41:33 +08001850 * Callback for a text node
Daniel Veillard19895052003-09-17 13:59:32 +00001851 *
1852 * Returns the newly allocated string or NULL if not needed or error
1853 */
1854static xmlNodePtr
1855xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1856 xmlNodePtr ret;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001857 const xmlChar *intern = NULL;
Daniel Veillard19895052003-09-17 13:59:32 +00001858
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001859 /*
1860 * Allocate
1861 */
Daniel Veillard19895052003-09-17 13:59:32 +00001862 if (ctxt->freeElems != NULL) {
1863 ret = ctxt->freeElems;
1864 ctxt->freeElems = ret->next;
1865 ctxt->freeElemsNr--;
Daniel Veillard19895052003-09-17 13:59:32 +00001866 } else {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001867 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard19895052003-09-17 13:59:32 +00001868 }
1869 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001870 xmlErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard19895052003-09-17 13:59:32 +00001871 return(NULL);
1872 }
Daniel Veillard8874b942005-08-25 13:19:21 +00001873 memset(ret, 0, sizeof(xmlNode));
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001874 /*
1875 * intern the formatting blanks found between tags, or the
1876 * very short strings
1877 */
1878 if (ctxt->dictNames) {
1879 xmlChar cur = str[len];
1880
Daniel Veillard8874b942005-08-25 13:19:21 +00001881 if ((len < (int) (2 * sizeof(void *))) &&
1882 (ctxt->options & XML_PARSE_COMPACT)) {
Daniel Veillard968a03a2012-08-13 12:41:33 +08001883 /* store the string in the node overriding properties and nsDef */
Daniel Veillard8874b942005-08-25 13:19:21 +00001884 xmlChar *tmp = (xmlChar *) &(ret->properties);
1885 memcpy(tmp, str, len);
1886 tmp[len] = 0;
1887 intern = tmp;
1888 } else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001889 ((cur == '<') && (str[len + 1] != '!')))) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001890 intern = xmlDictLookup(ctxt->dict, str, len);
William M. Brack76e95df2003-10-18 16:20:14 +00001891 } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
Daniel Veillarddca8cc72003-09-26 13:53:14 +00001892 (str[len + 1] != '!')) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001893 int i;
1894
1895 for (i = 1;i < len;i++) {
Daniel Veillard1a9b7082004-01-02 10:42:01 +00001896 if (!IS_BLANK_CH(str[i])) goto skip;
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001897 }
1898 intern = xmlDictLookup(ctxt->dict, str, len);
1899 }
1900 }
1901skip:
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001902 ret->type = XML_TEXT_NODE;
1903
1904 ret->name = xmlStringText;
William M. Brack9f797ab2004-07-28 07:40:12 +00001905 if (intern == NULL) {
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001906 ret->content = xmlStrndup(str, len);
William M. Brack9f797ab2004-07-28 07:40:12 +00001907 if (ret->content == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00001908 xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1909 xmlFree(ret);
William M. Brack9f797ab2004-07-28 07:40:12 +00001910 return(NULL);
1911 }
1912 } else
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001913 ret->content = (xmlChar *) intern;
1914
Daniel Veillard968a03a2012-08-13 12:41:33 +08001915 if (ctxt->linenumbers) {
1916 if (ctxt->input != NULL) {
1917 if (ctxt->input->line < 65535)
1918 ret->line = (short) ctxt->input->line;
1919 else {
1920 ret->line = 65535;
1921 if (ctxt->options & XML_PARSE_BIG_LINES)
Nick Wellnhoferd422b952017-10-09 13:37:42 +02001922 ret->psvi = (void *) (ptrdiff_t) ctxt->input->line;
Daniel Veillard968a03a2012-08-13 12:41:33 +08001923 }
1924 }
1925 }
Daniel Veillard45efd082008-07-07 13:52:52 +00001926
Daniel Veillarde96a2a42003-09-24 21:23:56 +00001927 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1928 xmlRegisterNodeDefaultValue(ret);
Daniel Veillard19895052003-09-17 13:59:32 +00001929 return(ret);
1930}
1931
Daniel Veillard4432df22003-09-28 18:58:27 +00001932#ifdef LIBXML_VALID_ENABLED
Daniel Veillard19895052003-09-17 13:59:32 +00001933/*
Daniel Veillarde57ec792003-09-10 10:50:59 +00001934 * xmlSAX2DecodeAttrEntities:
1935 * @ctxt: the parser context
1936 * @str: the input string
1937 * @len: the string length
Daniel Veillardf8e3db02012-09-11 13:26:36 +08001938 *
Daniel Veillarde57ec792003-09-10 10:50:59 +00001939 * Remove the entities from an attribute value
1940 *
1941 * Returns the newly allocated string or NULL if not needed or error
1942 */
1943static xmlChar *
1944xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1945 const xmlChar *end) {
1946 const xmlChar *in;
1947 xmlChar *ret;
1948
1949 in = str;
1950 while (in < end)
1951 if (*in++ == '&')
1952 goto decode;
1953 return(NULL);
1954decode:
1955 ctxt->depth++;
1956 ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1957 XML_SUBSTITUTE_REF, 0,0,0);
1958 ctxt->depth--;
1959 return(ret);
1960}
Daniel Veillard4432df22003-09-28 18:58:27 +00001961#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00001962
1963/**
1964 * xmlSAX2AttributeNs:
1965 * @ctx: the user data (XML parser context)
Daniel Veillard62998c02003-09-15 12:56:36 +00001966 * @localname: the local name of the attribute
1967 * @prefix: the attribute namespace prefix if available
1968 * @URI: the attribute namespace name if available
Daniel Veillarde57ec792003-09-10 10:50:59 +00001969 * @value: Start of the attribute value
1970 * @valueend: end of the attribute value
1971 *
1972 * Handle an attribute that has been read by the parser.
1973 * The default handling is to convert the attribute into an
1974 * DOM subtree and past it in a new xmlAttr element added to
1975 * the element.
1976 */
1977static void
1978xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1979 const xmlChar * localname,
1980 const xmlChar * prefix,
1981 const xmlChar * value,
1982 const xmlChar * valueend)
1983{
1984 xmlAttrPtr ret;
1985 xmlNsPtr namespace = NULL;
1986 xmlChar *dup = NULL;
1987
Daniel Veillarde57ec792003-09-10 10:50:59 +00001988 /*
1989 * Note: if prefix == NULL, the attribute is not in the default namespace
1990 */
1991 if (prefix != NULL)
1992 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1993
Daniel Veillard8a44e592003-09-15 14:50:06 +00001994 /*
1995 * allocate the node
1996 */
1997 if (ctxt->freeAttrs != NULL) {
1998 ret = ctxt->freeAttrs;
1999 ctxt->freeAttrs = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002000 ctxt->freeAttrsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002001 memset(ret, 0, sizeof(xmlAttr));
2002 ret->type = XML_ATTRIBUTE_NODE;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002003
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002004 ret->parent = ctxt->node;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002005 ret->doc = ctxt->myDoc;
2006 ret->ns = namespace;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002007
Daniel Veillard8a44e592003-09-15 14:50:06 +00002008 if (ctxt->dictNames)
2009 ret->name = localname;
2010 else
2011 ret->name = xmlStrdup(localname);
2012
Daniel Veillard9f7eb0b2003-09-17 10:26:25 +00002013 /* link at the end to preserv order, TODO speed up with a last */
2014 if (ctxt->node->properties == NULL) {
2015 ctxt->node->properties = ret;
2016 } else {
2017 xmlAttrPtr prev = ctxt->node->properties;
2018
2019 while (prev->next != NULL) prev = prev->next;
2020 prev->next = ret;
2021 ret->prev = prev;
2022 }
2023
Daniel Veillard8a44e592003-09-15 14:50:06 +00002024 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2025 xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
2026 } else {
2027 if (ctxt->dictNames)
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002028 ret = xmlNewNsPropEatName(ctxt->node, namespace,
Daniel Veillard8a44e592003-09-15 14:50:06 +00002029 (xmlChar *) localname, NULL);
2030 else
2031 ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
2032 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002033 xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002034 return;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002035 }
2036 }
2037
Daniel Veillard8a44e592003-09-15 14:50:06 +00002038 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
2039 xmlNodePtr tmp;
2040
Daniel Veillard19895052003-09-17 13:59:32 +00002041 /*
2042 * We know that if there is an entity reference, then
2043 * the string has been dup'ed and terminates with 0
2044 * otherwise with ' or "
2045 */
2046 if (*valueend != 0) {
2047 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2048 ret->children = tmp;
2049 ret->last = tmp;
2050 if (tmp != NULL) {
2051 tmp->doc = ret->doc;
2052 tmp->parent = (xmlNodePtr) ret;
2053 }
2054 } else {
2055 ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
2056 valueend - value);
2057 tmp = ret->children;
2058 while (tmp != NULL) {
Daniel Veillard8de5c0b2004-10-07 13:14:19 +00002059 tmp->doc = ret->doc;
Daniel Veillard19895052003-09-17 13:59:32 +00002060 tmp->parent = (xmlNodePtr) ret;
2061 if (tmp->next == NULL)
2062 ret->last = tmp;
2063 tmp = tmp->next;
2064 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002065 }
2066 } else if (value != NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002067 xmlNodePtr tmp;
2068
2069 tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2070 ret->children = tmp;
2071 ret->last = tmp;
2072 if (tmp != NULL) {
2073 tmp->doc = ret->doc;
2074 tmp->parent = (xmlNodePtr) ret;
2075 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002076 }
2077
Daniel Veillard4432df22003-09-28 18:58:27 +00002078#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002079 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2080 ctxt->myDoc && ctxt->myDoc->intSubset) {
2081 /*
2082 * If we don't substitute entities, the validation should be
2083 * done on a value with replaced entities anyway.
2084 */
2085 if (!ctxt->replaceEntities) {
2086 dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
2087 if (dup == NULL) {
Daniel Veillard62998c02003-09-15 12:56:36 +00002088 if (*valueend == 0) {
2089 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2090 ctxt->myDoc, ctxt->node, ret, value);
2091 } else {
2092 /*
2093 * That should already be normalized.
2094 * cheaper to finally allocate here than duplicate
2095 * entry points in the full validation code
2096 */
2097 dup = xmlStrndup(value, valueend - value);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002098
Daniel Veillard62998c02003-09-15 12:56:36 +00002099 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2100 ctxt->myDoc, ctxt->node, ret, dup);
2101 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002102 } else {
Daniel Veillard62998c02003-09-15 12:56:36 +00002103 /*
2104 * dup now contains a string of the flattened attribute
2105 * content with entities substitued. Check if we need to
2106 * apply an extra layer of normalization.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002107 * It need to be done twice ... it's an extra burden related
2108 * to the ability to keep references in attributes
2109 */
Daniel Veillard62998c02003-09-15 12:56:36 +00002110 if (ctxt->attsSpecial != NULL) {
2111 xmlChar *nvalnorm;
2112 xmlChar fn[50];
2113 xmlChar *fullname;
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002114
Daniel Veillard62998c02003-09-15 12:56:36 +00002115 fullname = xmlBuildQName(localname, prefix, fn, 50);
2116 if (fullname != NULL) {
2117 ctxt->vctxt.valid = 1;
2118 nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2119 &ctxt->vctxt, ctxt->myDoc,
2120 ctxt->node, fullname, dup);
2121 if (ctxt->vctxt.valid != 1)
2122 ctxt->valid = 0;
2123
2124 if ((fullname != fn) && (fullname != localname))
2125 xmlFree(fullname);
2126 if (nvalnorm != NULL) {
2127 xmlFree(dup);
2128 dup = nvalnorm;
2129 }
2130 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002131 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002132
2133 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2134 ctxt->myDoc, ctxt->node, ret, dup);
2135 }
2136 } else {
Daniel Veillard8e36e6a2003-09-10 10:50:59 +00002137 /*
2138 * if entities already have been substitued, then
2139 * the attribute as passed is already normalized
2140 */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002141 dup = xmlStrndup(value, valueend - value);
2142
2143 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2144 ctxt->myDoc, ctxt->node, ret, dup);
2145 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002146 } else
2147#endif /* LIBXML_VALID_ENABLED */
2148 if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002149 (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2150 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
2151 /*
2152 * when validating, the ID registration is done at the attribute
2153 * validation level. Otherwise we have to do specific handling here.
2154 */
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002155 if ((prefix == ctxt->str_xml) &&
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002156 (localname[0] == 'i') && (localname[1] == 'd') &&
2157 (localname[2] == 0)) {
2158 /*
2159 * Add the xml:id value
2160 *
2161 * Open issue: normalization of the value.
2162 */
2163 if (dup == NULL)
2164 dup = xmlStrndup(value, valueend - value);
Nicolas Le Cam52010c62013-06-16 08:55:08 +02002165#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 +00002166#ifdef LIBXML_VALID_ENABLED
Daniel Veillard68cb4b22004-04-18 20:55:39 +00002167 if (xmlValidateNCName(dup, 1) != 0) {
2168 xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2169 "xml:id : attribute value %s is not an NCName\n",
2170 (const char *) dup, NULL);
2171 }
William M. Brack3f147372004-05-22 01:09:26 +00002172#endif
Nicolas Le Cam52010c62013-06-16 08:55:08 +02002173#endif
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002174 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard54f9a4f2005-09-03 13:28:24 +00002175 } else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2176 /* might be worth duplicate entry points and not copy */
2177 if (dup == NULL)
2178 dup = xmlStrndup(value, valueend - value);
2179 xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2180 } else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2181 if (dup == NULL)
2182 dup = xmlStrndup(value, valueend - value);
2183 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
Daniel Veillard67f8b1c2004-04-09 21:51:49 +00002184 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002185 }
2186 if (dup != NULL)
2187 xmlFree(dup);
2188}
2189
2190/**
2191 * xmlSAX2StartElementNs:
2192 * @ctx: the user data (XML parser context)
2193 * @localname: the local name of the element
2194 * @prefix: the element namespace prefix if available
2195 * @URI: the element namespace name if available
2196 * @nb_namespaces: number of namespace definitions on that node
2197 * @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2198 * @nb_attributes: the number of attributes on that node
Daniel Veillard7a02cfe2003-09-25 12:18:34 +00002199 * @nb_defaulted: the number of defaulted attributes.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002200 * @attributes: pointer to the array of (localname/prefix/URI/value/end)
2201 * attribute values.
2202 *
2203 * SAX2 callback when an element start has been detected by the parser.
2204 * It provides the namespace informations for the element, as well as
2205 * the new namespace declarations on the element.
2206 */
2207void
2208xmlSAX2StartElementNs(void *ctx,
2209 const xmlChar *localname,
2210 const xmlChar *prefix,
2211 const xmlChar *URI,
2212 int nb_namespaces,
2213 const xmlChar **namespaces,
2214 int nb_attributes,
2215 int nb_defaulted,
2216 const xmlChar **attributes)
2217{
2218 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2219 xmlNodePtr ret;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002220 xmlNodePtr parent;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002221 xmlNsPtr last = NULL, ns;
2222 const xmlChar *uri, *pref;
Daniel Veillard77b77b12012-01-26 19:11:02 +08002223 xmlChar *lname = NULL;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002224 int i, j;
2225
Daniel Veillard34099b42004-11-04 17:34:35 +00002226 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002227 parent = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002228 /*
2229 * First check on validity:
2230 */
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002231 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002232 ((ctxt->myDoc->intSubset == NULL) ||
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002233 ((ctxt->myDoc->intSubset->notations == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002234 (ctxt->myDoc->intSubset->elements == NULL) &&
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002235 (ctxt->myDoc->intSubset->attributes == NULL) &&
Daniel Veillarde57ec792003-09-10 10:50:59 +00002236 (ctxt->myDoc->intSubset->entities == NULL)))) {
Daniel Veillard6c91aa32012-10-25 15:33:59 +08002237 xmlErrValid(ctxt, XML_DTD_NO_DTD,
Daniel Veillardf88d8cf2003-12-08 10:25:02 +00002238 "Validation failed: no DTD found !", NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002239 ctxt->validate = 0;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002240 }
2241
Daniel Veillard8a44e592003-09-15 14:50:06 +00002242 /*
Daniel Veillard77b77b12012-01-26 19:11:02 +08002243 * Take care of the rare case of an undefined namespace prefix
2244 */
2245 if ((prefix != NULL) && (URI == NULL)) {
2246 if (ctxt->dictNames) {
2247 const xmlChar *fullname;
2248
2249 fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
2250 if (fullname != NULL)
2251 localname = fullname;
2252 } else {
2253 lname = xmlBuildQName(localname, prefix, NULL, 0);
2254 }
2255 }
2256 /*
Daniel Veillard8a44e592003-09-15 14:50:06 +00002257 * allocate the node
2258 */
2259 if (ctxt->freeElems != NULL) {
2260 ret = ctxt->freeElems;
2261 ctxt->freeElems = ret->next;
Daniel Veillard19895052003-09-17 13:59:32 +00002262 ctxt->freeElemsNr--;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002263 memset(ret, 0, sizeof(xmlNode));
Elliott Hughes7fbecab2019-01-10 16:42:03 -08002264 ret->doc = ctxt->myDoc;
Daniel Veillard8a44e592003-09-15 14:50:06 +00002265 ret->type = XML_ELEMENT_NODE;
2266
2267 if (ctxt->dictNames)
2268 ret->name = localname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002269 else {
Daniel Veillard77b77b12012-01-26 19:11:02 +08002270 if (lname == NULL)
2271 ret->name = xmlStrdup(localname);
2272 else
2273 ret->name = lname;
William M. Brack9f797ab2004-07-28 07:40:12 +00002274 if (ret->name == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002275 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002276 return;
2277 }
2278 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002279 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2280 xmlRegisterNodeDefaultValue(ret);
2281 } else {
2282 if (ctxt->dictNames)
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002283 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
Daniel Veillard8a44e592003-09-15 14:50:06 +00002284 (xmlChar *) localname, NULL);
Daniel Veillard77b77b12012-01-26 19:11:02 +08002285 else if (lname == NULL)
Daniel Veillard8a44e592003-09-15 14:50:06 +00002286 ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
Daniel Veillard77b77b12012-01-26 19:11:02 +08002287 else
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002288 ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
Daniel Veillard77b77b12012-01-26 19:11:02 +08002289 (xmlChar *) lname, NULL);
Daniel Veillard8a44e592003-09-15 14:50:06 +00002290 if (ret == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002291 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
Daniel Veillard8a44e592003-09-15 14:50:06 +00002292 return;
2293 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002294 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002295 if (ctxt->linenumbers) {
Daniel Veillard3e35f8e2003-10-21 00:05:38 +00002296 if (ctxt->input != NULL) {
2297 if (ctxt->input->line < 65535)
2298 ret->line = (short) ctxt->input->line;
2299 else
2300 ret->line = 65535;
2301 }
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002302 }
Daniel Veillard8a44e592003-09-15 14:50:06 +00002303
Tim Elliott71a243d2012-01-17 19:25:08 -08002304 if (parent == NULL) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002305 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002306 }
2307 /*
2308 * Build the namespace list
2309 */
2310 for (i = 0,j = 0;j < nb_namespaces;j++) {
2311 pref = namespaces[i++];
2312 uri = namespaces[i++];
2313 ns = xmlNewNs(NULL, uri, pref);
2314 if (ns != NULL) {
2315 if (last == NULL) {
2316 ret->nsDef = last = ns;
2317 } else {
2318 last->next = ns;
2319 last = ns;
2320 }
2321 if ((URI != NULL) && (prefix == pref))
2322 ret->ns = ns;
2323 } else {
Daniel Veillardaa54d372010-09-09 18:17:47 +02002324 /*
2325 * any out of memory error would already have been raised
Nick Wellnhofer8bbe4502017-06-17 16:15:09 +02002326 * but we can't be guaranteed it's the actual error due to the
Daniel Veillardaa54d372010-09-09 18:17:47 +02002327 * API, best is to skip in this case
2328 */
2329 continue;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002330 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002331#ifdef LIBXML_VALID_ENABLED
Daniel Veillardd9e9c9d2003-09-18 22:03:46 +00002332 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2333 ctxt->myDoc && ctxt->myDoc->intSubset) {
2334 ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2335 ret, prefix, ns, uri);
2336 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002337#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002338 }
2339 ctxt->nodemem = -1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002340
2341 /*
2342 * We are parsing a new node.
2343 */
Elliott Hughes7fbecab2019-01-10 16:42:03 -08002344 if (nodePush(ctxt, ret) < 0) {
2345 xmlUnlinkNode(ret);
2346 xmlFreeNode(ret);
2347 return;
2348 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002349
2350 /*
2351 * Link the child element
2352 */
2353 if (parent != NULL) {
2354 if (parent->type == XML_ELEMENT_NODE) {
2355 xmlAddChild(parent, ret);
2356 } else {
2357 xmlAddSibling(parent, ret);
2358 }
2359 }
2360
2361 /*
2362 * Insert the defaulted attributes from the DTD only if requested:
2363 */
2364 if ((nb_defaulted != 0) &&
2365 ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2366 nb_attributes -= nb_defaulted;
2367
2368 /*
2369 * Search the namespace if it wasn't already found
William M. Brackbf5cf212004-08-31 06:47:17 +00002370 * Note that, if prefix is NULL, this searches for the default Ns
Daniel Veillarde57ec792003-09-10 10:50:59 +00002371 */
2372 if ((URI != NULL) && (ret->ns == NULL)) {
William M. Brackbf5cf212004-08-31 06:47:17 +00002373 ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillard6977c6c2006-01-04 14:03:10 +00002374 if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2375 ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2376 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002377 if (ret->ns == NULL) {
2378 ns = xmlNewNs(ret, NULL, prefix);
William M. Brack9f797ab2004-07-28 07:40:12 +00002379 if (ns == NULL) {
Daniel Veillard6977c6c2006-01-04 14:03:10 +00002380
William M. Brack42331a92004-07-29 07:07:16 +00002381 xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
William M. Brack9f797ab2004-07-28 07:40:12 +00002382 return;
2383 }
Daniel Veillard74eaec12009-08-26 15:57:20 +02002384 if (prefix != NULL)
2385 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2386 "Namespace prefix %s was not found\n",
2387 prefix, NULL);
2388 else
2389 xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2390 "Namespace default prefix was not found\n",
2391 NULL, NULL);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002392 }
2393 }
2394
2395 /*
2396 * process all the other attributes
2397 */
2398 if (nb_attributes > 0) {
2399 for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
Daniel Veillard1c989272012-01-26 19:43:06 +08002400 /*
2401 * Handle the rare case of an undefined atribute prefix
2402 */
2403 if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
2404 if (ctxt->dictNames) {
2405 const xmlChar *fullname;
2406
2407 fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
2408 attributes[j]);
2409 if (fullname != NULL) {
2410 xmlSAX2AttributeNs(ctxt, fullname, NULL,
2411 attributes[j+3], attributes[j+4]);
2412 continue;
2413 }
2414 } else {
2415 lname = xmlBuildQName(attributes[j], attributes[j+1],
2416 NULL, 0);
2417 if (lname != NULL) {
2418 xmlSAX2AttributeNs(ctxt, lname, NULL,
2419 attributes[j+3], attributes[j+4]);
2420 xmlFree(lname);
2421 continue;
2422 }
2423 }
2424 }
Daniel Veillarde57ec792003-09-10 10:50:59 +00002425 xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
Daniel Veillard1c989272012-01-26 19:43:06 +08002426 attributes[j+3], attributes[j+4]);
Daniel Veillarde57ec792003-09-10 10:50:59 +00002427 }
2428 }
2429
Daniel Veillard4432df22003-09-28 18:58:27 +00002430#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002431 /*
2432 * If it's the Document root, finish the DTD validation and
2433 * check the document root element for validity
2434 */
Daniel Veillardeff45a92004-10-29 12:10:55 +00002435 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002436 int chk;
2437
2438 chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2439 if (chk <= 0)
2440 ctxt->valid = 0;
2441 if (chk < 0)
2442 ctxt->wellFormed = 0;
2443 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillardeff45a92004-10-29 12:10:55 +00002444 ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002445 }
Daniel Veillard4432df22003-09-28 18:58:27 +00002446#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002447}
2448
2449/**
2450 * xmlSAX2EndElementNs:
2451 * @ctx: the user data (XML parser context)
2452 * @localname: the local name of the element
2453 * @prefix: the element namespace prefix if available
2454 * @URI: the element namespace name if available
2455 *
2456 * SAX2 callback when an element end has been detected by the parser.
2457 * It provides the namespace informations for the element.
2458 */
2459void
2460xmlSAX2EndElementNs(void *ctx,
2461 const xmlChar * localname ATTRIBUTE_UNUSED,
2462 const xmlChar * prefix ATTRIBUTE_UNUSED,
2463 const xmlChar * URI ATTRIBUTE_UNUSED)
2464{
2465 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2466 xmlParserNodeInfo node_info;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002467 xmlNodePtr cur;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002468
Daniel Veillard34099b42004-11-04 17:34:35 +00002469 if (ctx == NULL) return;
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002470 cur = ctxt->node;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002471 /* Capture end position and add node */
2472 if ((ctxt->record_info) && (cur != NULL)) {
2473 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2474 node_info.end_line = ctxt->input->line;
2475 node_info.node = cur;
2476 xmlParserAddNodeInfo(ctxt, &node_info);
2477 }
2478 ctxt->nodemem = -1;
2479
Daniel Veillard4432df22003-09-28 18:58:27 +00002480#ifdef LIBXML_VALID_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002481 if (ctxt->validate && ctxt->wellFormed &&
2482 ctxt->myDoc && ctxt->myDoc->intSubset)
2483 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
Daniel Veillard4432df22003-09-28 18:58:27 +00002484#endif /* LIBXML_VALID_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002485
2486 /*
2487 * end of parsing of this node.
2488 */
2489 nodePop(ctxt);
2490}
2491
Daniel Veillard1af9a412003-08-20 22:54:39 +00002492/**
2493 * xmlSAX2Reference:
2494 * @ctx: the user data (XML parser context)
2495 * @name: The entity name
2496 *
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002497 * called when an entity xmlSAX2Reference is detected.
Daniel Veillard1af9a412003-08-20 22:54:39 +00002498 */
2499void
2500xmlSAX2Reference(void *ctx, const xmlChar *name)
2501{
2502 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2503 xmlNodePtr ret;
2504
Daniel Veillard34099b42004-11-04 17:34:35 +00002505 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002506#ifdef DEBUG_SAX
2507 xmlGenericError(xmlGenericErrorContext,
2508 "SAX.xmlSAX2Reference(%s)\n", name);
2509#endif
2510 if (name[0] == '#')
2511 ret = xmlNewCharRef(ctxt->myDoc, name);
2512 else
2513 ret = xmlNewReference(ctxt->myDoc, name);
2514#ifdef DEBUG_SAX_TREE
2515 xmlGenericError(xmlGenericErrorContext,
2516 "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2517#endif
Daniel Veillardb242b082008-02-08 09:56:31 +00002518 if (xmlAddChild(ctxt->node, ret) == NULL) {
2519 xmlFreeNode(ret);
2520 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002521}
2522
2523/**
2524 * xmlSAX2Characters:
2525 * @ctx: the user data (XML parser context)
2526 * @ch: a xmlChar string
2527 * @len: the number of xmlChar
2528 *
2529 * receiving some chars from the parser.
2530 */
2531void
2532xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2533{
2534 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2535 xmlNodePtr lastChild;
2536
Daniel Veillard34099b42004-11-04 17:34:35 +00002537 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002538#ifdef DEBUG_SAX
2539 xmlGenericError(xmlGenericErrorContext,
2540 "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2541#endif
2542 /*
2543 * Handle the data if any. If there is no child
2544 * add it as content, otherwise if the last child is text,
2545 * concatenate it, else create a new node of type text.
2546 */
2547
2548 if (ctxt->node == NULL) {
2549#ifdef DEBUG_SAX_TREE
2550 xmlGenericError(xmlGenericErrorContext,
2551 "add chars: ctxt->node == NULL !\n");
2552#endif
2553 return;
2554 }
Daniel Veillard19895052003-09-17 13:59:32 +00002555 lastChild = ctxt->node->last;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002556#ifdef DEBUG_SAX_TREE
2557 xmlGenericError(xmlGenericErrorContext,
2558 "add chars to %s \n", ctxt->node->name);
2559#endif
2560
2561 /*
2562 * Here we needed an accelerator mechanism in case of very large
2563 * elements. Use an attribute in the structure !!!
2564 */
2565 if (lastChild == NULL) {
Daniel Veillard19895052003-09-17 13:59:32 +00002566 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2567 if (lastChild != NULL) {
2568 ctxt->node->children = lastChild;
2569 ctxt->node->last = lastChild;
2570 lastChild->parent = ctxt->node;
2571 lastChild->doc = ctxt->node->doc;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002572 ctxt->nodelen = len;
2573 ctxt->nodemem = len + 1;
William M. Bracka3215c72004-07-31 16:24:01 +00002574 } else {
2575 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2576 return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002577 }
2578 } else {
2579 int coalesceText = (lastChild != NULL) &&
2580 (lastChild->type == XML_TEXT_NODE) &&
2581 (lastChild->name == xmlStringText);
2582 if ((coalesceText) && (ctxt->nodemem != 0)) {
2583 /*
2584 * The whole point of maintaining nodelen and nodemem,
2585 * xmlTextConcat is too costly, i.e. compute length,
2586 * reallocate a new buffer, move data, append ch. Here
2587 * We try to minimaze realloc() uses and avoid copying
2588 * and recomputing length over and over.
2589 */
Daniel Veillard8874b942005-08-25 13:19:21 +00002590 if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2591 lastChild->content = xmlStrdup(lastChild->content);
2592 lastChild->properties = NULL;
2593 } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2594 (xmlDictOwns(ctxt->dict, lastChild->content))) {
Daniel Veillard2b0f8792003-10-10 19:36:36 +00002595 lastChild->content = xmlStrdup(lastChild->content);
2596 }
Gaurav3e0eec42014-06-13 14:45:20 +08002597 if (lastChild->content == NULL) {
2598 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL");
Daniel Veillarda6ea72a2014-07-14 20:29:34 +08002599 return;
Gaurav3e0eec42014-06-13 14:45:20 +08002600 }
Daniel Veillard97ff9b32009-01-18 21:43:30 +00002601 if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
Daniel Veillard1fb2e0d2009-01-18 14:08:36 +00002602 ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2603 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2604 return;
2605 }
Daniel Veillardf8e3db02012-09-11 13:26:36 +08002606 if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002607 (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
Daniel Veillard1fb2e0d2009-01-18 14:08:36 +00002608 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2609 return;
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002610 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002611 if (ctxt->nodelen + len >= ctxt->nodemem) {
2612 xmlChar *newbuf;
Daniel Veillard1dc9feb2008-11-17 15:59:21 +00002613 size_t size;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002614
2615 size = ctxt->nodemem + len;
2616 size *= 2;
2617 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2618 if (newbuf == NULL) {
William M. Brack42331a92004-07-29 07:07:16 +00002619 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002620 return;
2621 }
2622 ctxt->nodemem = size;
2623 lastChild->content = newbuf;
2624 }
2625 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2626 ctxt->nodelen += len;
2627 lastChild->content[ctxt->nodelen] = 0;
2628 } else if (coalesceText) {
2629 if (xmlTextConcat(lastChild, ch, len)) {
William M. Brack42331a92004-07-29 07:07:16 +00002630 xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
Daniel Veillard1af9a412003-08-20 22:54:39 +00002631 }
2632 if (ctxt->node->children != NULL) {
2633 ctxt->nodelen = xmlStrlen(lastChild->content);
2634 ctxt->nodemem = ctxt->nodelen + 1;
2635 }
2636 } else {
2637 /* Mixed content, first time */
Daniel Veillard19895052003-09-17 13:59:32 +00002638 lastChild = xmlSAX2TextNode(ctxt, ch, len);
2639 if (lastChild != NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002640 xmlAddChild(ctxt->node, lastChild);
2641 if (ctxt->node->children != NULL) {
2642 ctxt->nodelen = len;
2643 ctxt->nodemem = len + 1;
2644 }
2645 }
2646 }
2647 }
2648}
2649
2650/**
2651 * xmlSAX2IgnorableWhitespace:
2652 * @ctx: the user data (XML parser context)
2653 * @ch: a xmlChar string
2654 * @len: the number of xmlChar
2655 *
2656 * receiving some ignorable whitespaces from the parser.
2657 * UNUSED: by default the DOM building will use xmlSAX2Characters
2658 */
2659void
2660xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2661{
2662 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2663#ifdef DEBUG_SAX
2664 xmlGenericError(xmlGenericErrorContext,
2665 "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2666#endif
2667}
2668
2669/**
2670 * xmlSAX2ProcessingInstruction:
2671 * @ctx: the user data (XML parser context)
2672 * @target: the target name
2673 * @data: the PI data's
2674 *
2675 * A processing instruction has been parsed.
2676 */
2677void
2678xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2679 const xmlChar *data)
2680{
2681 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2682 xmlNodePtr ret;
Daniel Veillard6128c012004-11-08 17:16:15 +00002683 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002684
Daniel Veillard34099b42004-11-04 17:34:35 +00002685 if (ctx == NULL) return;
Daniel Veillard6128c012004-11-08 17:16:15 +00002686 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002687#ifdef DEBUG_SAX
2688 xmlGenericError(xmlGenericErrorContext,
2689 "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2690#endif
2691
Daniel Veillard03a53c32004-10-26 16:06:51 +00002692 ret = xmlNewDocPI(ctxt->myDoc, target, data);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002693 if (ret == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002694
Daniel Veillard73da77e2005-08-24 14:05:37 +00002695 if (ctxt->linenumbers) {
2696 if (ctxt->input != NULL) {
2697 if (ctxt->input->line < 65535)
2698 ret->line = (short) ctxt->input->line;
2699 else
2700 ret->line = 65535;
2701 }
2702 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002703 if (ctxt->inSubset == 1) {
2704 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2705 return;
2706 } else if (ctxt->inSubset == 2) {
2707 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2708 return;
2709 }
Tim Elliott71a243d2012-01-17 19:25:08 -08002710 if (parent == NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002711#ifdef DEBUG_SAX_TREE
2712 xmlGenericError(xmlGenericErrorContext,
2713 "Setting PI %s as root\n", target);
2714#endif
2715 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2716 return;
2717 }
2718 if (parent->type == XML_ELEMENT_NODE) {
2719#ifdef DEBUG_SAX_TREE
2720 xmlGenericError(xmlGenericErrorContext,
2721 "adding PI %s child to %s\n", target, parent->name);
2722#endif
2723 xmlAddChild(parent, ret);
2724 } else {
2725#ifdef DEBUG_SAX_TREE
2726 xmlGenericError(xmlGenericErrorContext,
2727 "adding PI %s sibling to ", target);
2728 xmlDebugDumpOneNode(stderr, parent, 0);
2729#endif
2730 xmlAddSibling(parent, ret);
2731 }
2732}
2733
2734/**
2735 * xmlSAX2Comment:
2736 * @ctx: the user data (XML parser context)
2737 * @value: the xmlSAX2Comment content
2738 *
2739 * A xmlSAX2Comment has been parsed.
2740 */
2741void
2742xmlSAX2Comment(void *ctx, const xmlChar *value)
2743{
2744 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2745 xmlNodePtr ret;
Daniel Veillard34099b42004-11-04 17:34:35 +00002746 xmlNodePtr parent;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002747
Daniel Veillard34099b42004-11-04 17:34:35 +00002748 if (ctx == NULL) return;
2749 parent = ctxt->node;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002750#ifdef DEBUG_SAX
2751 xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2752#endif
2753 ret = xmlNewDocComment(ctxt->myDoc, value);
2754 if (ret == NULL) return;
Daniel Veillard73da77e2005-08-24 14:05:37 +00002755 if (ctxt->linenumbers) {
2756 if (ctxt->input != NULL) {
2757 if (ctxt->input->line < 65535)
2758 ret->line = (short) ctxt->input->line;
2759 else
2760 ret->line = 65535;
2761 }
2762 }
Daniel Veillard1af9a412003-08-20 22:54:39 +00002763
2764 if (ctxt->inSubset == 1) {
2765 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2766 return;
2767 } else if (ctxt->inSubset == 2) {
2768 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2769 return;
2770 }
Tim Elliott71a243d2012-01-17 19:25:08 -08002771 if (parent == NULL) {
Daniel Veillard1af9a412003-08-20 22:54:39 +00002772#ifdef DEBUG_SAX_TREE
2773 xmlGenericError(xmlGenericErrorContext,
2774 "Setting xmlSAX2Comment as root\n");
2775#endif
2776 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2777 return;
2778 }
2779 if (parent->type == XML_ELEMENT_NODE) {
2780#ifdef DEBUG_SAX_TREE
2781 xmlGenericError(xmlGenericErrorContext,
2782 "adding xmlSAX2Comment child to %s\n", parent->name);
2783#endif
2784 xmlAddChild(parent, ret);
2785 } else {
2786#ifdef DEBUG_SAX_TREE
2787 xmlGenericError(xmlGenericErrorContext,
2788 "adding xmlSAX2Comment sibling to ");
2789 xmlDebugDumpOneNode(stderr, parent, 0);
2790#endif
2791 xmlAddSibling(parent, ret);
2792 }
2793}
2794
2795/**
2796 * xmlSAX2CDataBlock:
2797 * @ctx: the user data (XML parser context)
2798 * @value: The pcdata content
2799 * @len: the block length
2800 *
2801 * called when a pcdata block has been parsed
2802 */
2803void
2804xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2805{
2806 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2807 xmlNodePtr ret, lastChild;
2808
Daniel Veillard34099b42004-11-04 17:34:35 +00002809 if (ctx == NULL) return;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002810#ifdef DEBUG_SAX
2811 xmlGenericError(xmlGenericErrorContext,
2812 "SAX.pcdata(%.10s, %d)\n", value, len);
2813#endif
2814 lastChild = xmlGetLastChild(ctxt->node);
2815#ifdef DEBUG_SAX_TREE
2816 xmlGenericError(xmlGenericErrorContext,
2817 "add chars to %s \n", ctxt->node->name);
2818#endif
2819 if ((lastChild != NULL) &&
2820 (lastChild->type == XML_CDATA_SECTION_NODE)) {
2821 xmlTextConcat(lastChild, value, len);
2822 } else {
2823 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
David Tardon07418012017-04-05 10:22:40 +02002824 if (xmlAddChild(ctxt->node, ret) == NULL)
2825 xmlFreeNode(ret);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002826 }
2827}
2828
Daniel Veillard62998c02003-09-15 12:56:36 +00002829static int xmlSAX2DefaultVersionValue = 2;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002830
Daniel Veillard81273902003-09-30 00:43:48 +00002831#ifdef LIBXML_SAX1_ENABLED
Daniel Veillarde57ec792003-09-10 10:50:59 +00002832/**
2833 * xmlSAXDefaultVersion:
2834 * @version: the version, 1 or 2
2835 *
2836 * Set the default version of SAX used globally by the library.
William M. Brack96d2eff2004-06-30 11:48:47 +00002837 * By default, during initialization the default is set to 2.
2838 * Note that it is generally a better coding style to use
2839 * xmlSAXVersion() to set up the version explicitly for a given
2840 * parsing context.
Daniel Veillarde57ec792003-09-10 10:50:59 +00002841 *
2842 * Returns the previous value in case of success and -1 in case of error.
2843 */
2844int
2845xmlSAXDefaultVersion(int version)
2846{
2847 int ret = xmlSAX2DefaultVersionValue;
2848
2849 if ((version != 1) && (version != 2))
2850 return(-1);
2851 xmlSAX2DefaultVersionValue = version;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002852 return(ret);
2853}
Daniel Veillard81273902003-09-30 00:43:48 +00002854#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002855
2856/**
2857 * xmlSAXVersion:
2858 * @hdlr: the SAX handler
2859 * @version: the version, 1 or 2
2860 *
2861 * Initialize the default XML SAX handler according to the version
2862 *
2863 * Returns 0 in case of success and -1 in case of error.
2864 */
2865int
2866xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2867{
2868 if (hdlr == NULL) return(-1);
Daniel Veillard81273902003-09-30 00:43:48 +00002869 if (version == 2) {
Daniel Veillarde57ec792003-09-10 10:50:59 +00002870 hdlr->startElement = NULL;
2871 hdlr->endElement = NULL;
2872 hdlr->startElementNs = xmlSAX2StartElementNs;
2873 hdlr->endElementNs = xmlSAX2EndElementNs;
Daniel Veillardffbbed42003-10-10 14:46:54 +00002874 hdlr->serror = NULL;
Daniel Veillard092643b2003-09-25 14:29:29 +00002875 hdlr->initialized = XML_SAX2_MAGIC;
Daniel Veillard81273902003-09-30 00:43:48 +00002876#ifdef LIBXML_SAX1_ENABLED
2877 } else if (version == 1) {
2878 hdlr->startElement = xmlSAX2StartElement;
2879 hdlr->endElement = xmlSAX2EndElement;
2880 hdlr->initialized = 1;
2881#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillarde57ec792003-09-10 10:50:59 +00002882 } else
2883 return(-1);
Daniel Veillard1af9a412003-08-20 22:54:39 +00002884 hdlr->internalSubset = xmlSAX2InternalSubset;
2885 hdlr->externalSubset = xmlSAX2ExternalSubset;
2886 hdlr->isStandalone = xmlSAX2IsStandalone;
2887 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2888 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2889 hdlr->resolveEntity = xmlSAX2ResolveEntity;
2890 hdlr->getEntity = xmlSAX2GetEntity;
2891 hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2892 hdlr->entityDecl = xmlSAX2EntityDecl;
2893 hdlr->attributeDecl = xmlSAX2AttributeDecl;
2894 hdlr->elementDecl = xmlSAX2ElementDecl;
2895 hdlr->notationDecl = xmlSAX2NotationDecl;
2896 hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2897 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2898 hdlr->startDocument = xmlSAX2StartDocument;
2899 hdlr->endDocument = xmlSAX2EndDocument;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002900 hdlr->reference = xmlSAX2Reference;
2901 hdlr->characters = xmlSAX2Characters;
2902 hdlr->cdataBlock = xmlSAX2CDataBlock;
2903 hdlr->ignorableWhitespace = xmlSAX2Characters;
2904 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2905 hdlr->comment = xmlSAX2Comment;
Daniel Veillarde57ec792003-09-10 10:50:59 +00002906 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002907 hdlr->error = xmlParserError;
2908 hdlr->fatalError = xmlParserError;
2909
Daniel Veillarde57ec792003-09-10 10:50:59 +00002910 return(0);
2911}
2912
2913/**
2914 * xmlSAX2InitDefaultSAXHandler:
2915 * @hdlr: the SAX handler
2916 * @warning: flag if non-zero sets the handler warning procedure
2917 *
2918 * Initialize the default XML SAX2 handler
2919 */
2920void
2921xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2922{
2923 if ((hdlr == NULL) || (hdlr->initialized != 0))
2924 return;
2925
2926 xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2927 if (warning == 0)
2928 hdlr->warning = NULL;
2929 else
2930 hdlr->warning = xmlParserWarning;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002931}
2932
2933/**
2934 * xmlDefaultSAXHandlerInit:
2935 *
2936 * Initialize the default SAX2 handler
2937 */
2938void
2939xmlDefaultSAXHandlerInit(void)
2940{
Daniel Veillard81273902003-09-30 00:43:48 +00002941#ifdef LIBXML_SAX1_ENABLED
Daniel Veillard092643b2003-09-25 14:29:29 +00002942 xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
Daniel Veillard81273902003-09-30 00:43:48 +00002943#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillard1af9a412003-08-20 22:54:39 +00002944}
2945
2946#ifdef LIBXML_HTML_ENABLED
2947
2948/**
2949 * xmlSAX2InitHtmlDefaultSAXHandler:
2950 * @hdlr: the SAX handler
2951 *
2952 * Initialize the default HTML SAX2 handler
2953 */
2954void
2955xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2956{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00002957 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00002958 return;
2959
2960 hdlr->internalSubset = xmlSAX2InternalSubset;
2961 hdlr->externalSubset = NULL;
2962 hdlr->isStandalone = NULL;
2963 hdlr->hasInternalSubset = NULL;
2964 hdlr->hasExternalSubset = NULL;
2965 hdlr->resolveEntity = NULL;
2966 hdlr->getEntity = xmlSAX2GetEntity;
2967 hdlr->getParameterEntity = NULL;
2968 hdlr->entityDecl = NULL;
2969 hdlr->attributeDecl = NULL;
2970 hdlr->elementDecl = NULL;
2971 hdlr->notationDecl = NULL;
2972 hdlr->unparsedEntityDecl = NULL;
2973 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2974 hdlr->startDocument = xmlSAX2StartDocument;
2975 hdlr->endDocument = xmlSAX2EndDocument;
2976 hdlr->startElement = xmlSAX2StartElement;
2977 hdlr->endElement = xmlSAX2EndElement;
2978 hdlr->reference = NULL;
2979 hdlr->characters = xmlSAX2Characters;
2980 hdlr->cdataBlock = xmlSAX2CDataBlock;
2981 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
Daniel Veillardfc484dd2004-10-22 14:34:23 +00002982 hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002983 hdlr->comment = xmlSAX2Comment;
2984 hdlr->warning = xmlParserWarning;
2985 hdlr->error = xmlParserError;
2986 hdlr->fatalError = xmlParserError;
2987
Daniel Veillard092643b2003-09-25 14:29:29 +00002988 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00002989}
2990
2991/**
2992 * htmlDefaultSAXHandlerInit:
2993 *
2994 * Initialize the default SAX handler
2995 */
2996void
2997htmlDefaultSAXHandlerInit(void)
2998{
Daniel Veillard092643b2003-09-25 14:29:29 +00002999 xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00003000}
3001
3002#endif /* LIBXML_HTML_ENABLED */
3003
3004#ifdef LIBXML_DOCB_ENABLED
3005
3006/**
3007 * xmlSAX2InitDocbDefaultSAXHandler:
3008 * @hdlr: the SAX handler
3009 *
3010 * Initialize the default DocBook SAX2 handler
3011 */
3012void
3013xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
3014{
Daniel Veillard2a4fb5a2004-11-08 14:02:18 +00003015 if ((hdlr == NULL) || (hdlr->initialized != 0))
Daniel Veillard1af9a412003-08-20 22:54:39 +00003016 return;
3017
3018 hdlr->internalSubset = xmlSAX2InternalSubset;
3019 hdlr->externalSubset = NULL;
3020 hdlr->isStandalone = xmlSAX2IsStandalone;
3021 hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
3022 hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
3023 hdlr->resolveEntity = xmlSAX2ResolveEntity;
3024 hdlr->getEntity = xmlSAX2GetEntity;
3025 hdlr->getParameterEntity = NULL;
3026 hdlr->entityDecl = xmlSAX2EntityDecl;
3027 hdlr->attributeDecl = NULL;
3028 hdlr->elementDecl = NULL;
3029 hdlr->notationDecl = NULL;
3030 hdlr->unparsedEntityDecl = NULL;
3031 hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
3032 hdlr->startDocument = xmlSAX2StartDocument;
3033 hdlr->endDocument = xmlSAX2EndDocument;
3034 hdlr->startElement = xmlSAX2StartElement;
3035 hdlr->endElement = xmlSAX2EndElement;
3036 hdlr->reference = xmlSAX2Reference;
3037 hdlr->characters = xmlSAX2Characters;
3038 hdlr->cdataBlock = NULL;
3039 hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
3040 hdlr->processingInstruction = NULL;
3041 hdlr->comment = xmlSAX2Comment;
3042 hdlr->warning = xmlParserWarning;
3043 hdlr->error = xmlParserError;
3044 hdlr->fatalError = xmlParserError;
3045
Daniel Veillardffbbed42003-10-10 14:46:54 +00003046 hdlr->initialized = 1;
Daniel Veillard1af9a412003-08-20 22:54:39 +00003047}
3048
3049/**
3050 * docbDefaultSAXHandlerInit:
3051 *
3052 * Initialize the default SAX handler
3053 */
3054void
3055docbDefaultSAXHandlerInit(void)
3056{
Daniel Veillard092643b2003-09-25 14:29:29 +00003057 xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
Daniel Veillard1af9a412003-08-20 22:54:39 +00003058}
3059
3060#endif /* LIBXML_DOCB_ENABLED */
Daniel Veillard5d4644e2005-04-01 13:11:58 +00003061#define bottom_SAX2
3062#include "elfgcchack.h"